ES6中提出的对象展开运算符”…“就是用来展开元素的。有了它就不用代码循环遍历了,偷懒专用。
合并数组
展开原有数组中的所有元素,可以合并成一个新的数组
var a=[1,2,3]; var b=[4,5,6]; var c=[...a,...b]; console.log(c) // 输出:[1, 2, 3, 4, 5, 6]
合并对象
展开对象中的所有属性,可以合并成一个新的对象
var person1 = { name: '小明', age: 18, sex: '男', } var hobby = { music: '伤感类歌曲', like: '吃饭、睡觉、打游戏', } var xiaoMing = {...person1,...hobby} console.log(xiaoMing) // 输出:{name: "小明", age: 18, sex: "男", music: "伤感类歌曲", like: "吃饭、睡觉、打游戏"}
合并对象并修改属性
修改对象其实也是合并对象,只不过是:当几个对象中含有同名参数时,后面的会把前面同名属性值覆盖掉。
var person1 = { name: '小明', age: 18, sex: '男', } var hobby = { music: '伤感类歌曲', like: '吃饭、睡觉、打游戏', } var xiaoHong = { ...person1, ...{name: '小红',sex:'女'}, ...hobby } console.log(xiaoHong) // 输出:{name: "小红", age: 18, sex: "女", music: "伤感类歌曲", like: "吃饭、睡觉、打游戏"}
对象展开运算符是浅拷贝还是深拷贝?
先来了解下,浅拷贝和深拷贝各自的含义:
数据可以分为两大类:一类是基本数据,一类是引用数据;而数据存储位置又可分为栈和堆。
基本数据是存储在栈中的,深拷贝和浅拷贝操作的都是真实的数据,所以没有区别。
故而,深拷贝和浅拷贝主要是针对引用数据来说的。
引用数据,相当于是在栈中存储了一个地址,这个地址指向堆中的真实数据,
浅拷贝,相当于把栈中的地址给了一个新的对象,新对象和旧对象指向的都是堆中同一个数据,所以无论哪个对象发生变化都会影响堆中的这个数据;
深拷贝,是在堆中重新开辟一片空间,生成了一个新的数据区域,这样新对象指向的是新的数据,旧对象指向的是旧的数据,所以这两个数据区无论谁发生变化都不会影响另一个。
下面看一个浅拷贝的例子:
var person1 = { name: '小明', age: 18, sex: '男', } var xiaoHong = person1; // 这里只是将引用变量person1给了xiaoHong xiaoHong.name = '小红'; console.log(person1) // 输出:{name: "小红", age: 18, sex: "男"} console.log(xiaoHong)// 输出:{name: "小红", age: 18, sex: "男"}
由上面的例子,很清楚的看到:当xiaoHong的name属性值变化了之后,person1的name属性值也发生变化了,所以两个对象指向的是同一个数据区域,是浅拷贝。
那么对象展开运算符是浅拷贝还是深拷贝呢?看下面例子:
var person1 = { name: '小明', age: 18, sex: '男', } var xiaoHong = {...person1} xiaoHong.name = '小红'; console.log(person1) // 输出: {name: "小明", age: 18, sex: "男"} console.log(xiaoHong)// 输出: {name: "小红", age: 18, sex: "男"}
哎,用对象展开符的xiaoHong的name属性变化了之后,person1的name属性没有变化呀!难道对象扩展符是深拷贝?别急,往下看。
再看下面的例子,对象中包含着第二层数据对象。
var person1 = { name: '小明', age: 18, sex: '男', hobby: { music: '伤感类歌曲', like: '吃饭、睡觉、打游戏', } } var xiaoHong = {...person1} xiaoHong.name = '小红'; xiaoHong.hobby.music = '小清新歌曲'; console.log(person1) // 输出: {name: "小明", age: 18, sex: "男", hobby: {music: "小清新歌曲",like: "吃饭、睡觉、打游戏"}} console.log(xiaoHong) // 输出: {name: "小红", age: 18, sex: "男", hobby: {music: "小清新歌曲",like: "吃饭、睡觉、打游戏"}}
看上面代码片段,对比新旧两个对象的输出:
你发现对象展开运算符并不是深拷贝,而是浅拷贝。
我感觉可以这么理解:对象展开预算符相当于展开遍历了对象的第一层数据,第一层数据如果是基本数据,就是简单的值;第一层数据若是引用数据,就是浅拷贝。