关于JS中的对象展开运算符“...”的一些思考

最近笔者在写vue的时候用到了JS中的新特性展开运算符(ES6、ES7新提出)。展开运算符的加入可以使我们在写JS代码时更加简洁灵活。可用于函数调用、解构赋值等方面。具体可以参考这篇博客:  ECMAScript 6学习笔记(一):展开运算符 。

今天笔者想说说对象展开运算符的使用,对象展开运算符提出于ES7的草案之中,可以这样使用:

let shortcuts = {
    attr1: 3,
    attr2: 4
}
let shortcuts2 = {}
shortcuts2 = {...shortcuts}

上面的这种用法实际上相当于是:

shortcuts2 = {attr1: 3, attr2: 4}

这种写法有好多好处,比如可以合并对象或者将一个对象插入另外一个对象中去:

let a = { x: 1, y: 2 }
let b = { z: 3 }
let ab = { ...a, ...b }
ab // { x: 1, y: 2, z: 3 }

以及与shortcuts2 = shortcuts这种直接引用赋值写法的区别。我们知道对于引用类型来说赋值操作其实传递的只是这个对象的地址(粗浅的说),意味着如果按照shortcuts2 = shortcuts的写法的话当改变shortcuts2中的属性的值的话shortcuts也会同样改变。换言之shortcuts和shortcuts2两个变量指向了同一段内存地址。但是如果是 shortcuts2 = { ...shortcuts },这样的写的话,由于shortcuts中的属性类型都是基本类型,相当于是新建了一个对象,此时改变shortcuts2中的属性值,shortcuts将不受影响——某种意义上实现了对象之间的深拷贝,但是仅限于其属性都为基本类型的情况(或者说只进行了一层的深拷贝),如果该对象中的属性还有引用类型的话,如下:

let obj1 = {
  attri1: [б, 6, 0],
  attri2: 4,
  attri4: 5
}
let obj2 = {...obj1}
console.log('obj2: ', obj2)
obj2.attri2 = 888 
obj2.attri1[0] = 7
// obj2.attri1 = [8, 8, 8, 8]
console.log('obj1:', obj1)
console.log('obj2:', obj2)

obj是一个既包含引用类型又包含基本类型属性的对象,将其利用对象展开符赋值给obj2之后,修改obj2中的属性值 

此时的输出结果是这样的:

 

obj2中的attri1数组中的第一个元素替换为7之后,obj1中的attri1也收到了影响,但attri2是基本类型不受影响:说明对象展开运算符本质上是将obj1中的属性按顺序赋值给了obj2,此时基本类型进行的是值传递,而引用类型进行的是引用传递

因此在这种情况下要谨慎使用对象展开符,其和一般的引用传递过程有一定的区别。 

 

参考: http://www.cnblogs.com/mingjiezhang/p/5903026.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章