从拷贝说起
数组拷贝
在ES5 经常会遇到数组和对象的浅拷贝,我们都知道数组和对象都是引用类型,所以不能像字符串那样直接赋值,在ES5中 数组和对象的拷贝都是通过循环来实现的。
var arr1 = [1, 2, 3];
var arr2 = [];
arr1.forEach(function(value){
arr2.push(value);
})
console.log(arr2); // [1, 2, 3]
//等效于 concat() 方法用于连接两个或多个数组,
//该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本
var arr2 = [].concat(arr1); // [1, 2, 3]
//slice() 方法可从已有的数组中返回选定的元素。arrayObject.slice(start,end)
var arr3 = arr1.slice(0); //[1, 2, 3]
字面量对象拷贝
//es5 中针对字面量对象的拷贝方式比较少,只能循环
let obj = {a: 1, b: 2};
let copy1 = {};
for(let key in obj) {
copy1[key] = obj[key]
}
let copy2 = JSON.parse(JSON.stringify(obj))
ES6的展开语法
var arr1 = [1, 2, 3];
var arr2 = [...arr1];
arr1.push(4)
console.log(arr1); //[1, 2, 3, 4]
console.log(arr2); //[1, 2, 3]
//使用...展开语法 比较简洁地表达了把arr1中的每一项展开放入arr2中。
let obj = {a: 1, b: 2};
let copy = {...obj};
Tips: 这里有必要说明一下,以上的方法都是浅拷贝(只拷贝数组和对象的第一层结构)的过程,对于数组和对象第一层以后的内容,如果是引用类型的存储方式,则不会进行拷贝操作,也就是不会进行深拷贝。
展开语法的使用场景
//在字符串中的使用
const arr = [...'imooc'];
console.log(arr); // ["i", "m", "o", "o", "c"]
等效于es5中
const arr = 'imooc'.split('');
console.log(arr); // ["i", "m", "o", "o", "c"]
//在数组中的使用
//ES5 中对一个数组的拷贝,在数组的操作中还有添加、合并等操作的时候,
//需要调用数组的 slice ()、concat ()、unshift () 等方法,或者组合使用这些方法
const arr1 = [1, 2];
const arr2 = ['a', ...arr1];
const arr3 = [...arr1, ...arr2];
console.log(arr2); // ['a', 1, 2]
console.log(arr3); // [1, 2, 'a', 1, 2]
//在字面量对象中的使用
const obj1 = {a: 1, b: 2};
const obj2 = {...obj1, c: 30};
console.log(obj2); // {a:1, b:2, c:30}
const obj3 = {b: 20, c: 30};
const obj4 = {...obj2, ...obj3}; // 合并对象
console.log(obj4); // {a:1, b:20, c:30}
小结
- 可以把 ... 加数组或字面量当作数组或字面量中的一项,任意放入数组或字面量中不同的位置;
- 可以通过展开语法对数组和字面量进行浅拷贝;
- 在函数传参数直接把数组中的项进行展开就可以达到传递多个参数的目的。