概念理解
1.数组
- 数组浅拷贝
数组浅拷贝:只能拷贝数组的第一层基本数据类型数据,无法切断数组内部引用类型数据的引用关系。
简而言之也就是说第一层数据可以修改,而修改第二层数据会影响原数组。
为了更全面了解数组的拷贝,我们举例复杂数组:
方法:slice(),concat()和es6拓展运算符等
var arr = [1,{ name: 'Amy', age: 18 }, [2, 3, 4], function () { }];
var target = arr.concat() || arr.slice();
target[0] = 2;
target[2][1] = 100;
console.log(arr);
console.log(target);
结论:我们通过concat()和slice()方法(或者使用es6拓展运算符)浅拷贝target,然后通过修改target打印结果发现修改数组第一层数据是不影响原数组的,但是第二层就会影响到,说明这种拷贝方式无法切断内部引用关系,属于浅拷贝。
- 数组深拷贝
数组深拷贝:彻底切断了数组内引用类型的引用关系。
方法:JSON.parse()与 JSON.stringify()
var arr = [1, { name: 'Amy', age: 18 }, [2, 3, 4], function () { }];
var target = JSON.parse(JSON.stringify(arr))
target[0] = 2;
target[2][1] = 100;
console.log(arr);
console.log(target);
结论:通过上面的运行结果,我们发现使用JSON.parse与JSON.stringify可以实现数组的深拷贝。但是拷贝后的数组使用JSON.stringify(…) 在对象中遇到 undefined 、 function 和 symbol 时会自动将其忽略在数组中则会返回 null(以保证单元位置不变)。
2.对象
- 对象浅拷贝
对象浅拷贝:只能拷贝对象中的基本数据类型数据,无法切断对象内部引用类型数据的引用关系。
方法:es6 Object.assign()
var source2 = {0:1, 1:null, 2:undefined, 3:{name: 'anjou', age: undefined, sex: null}, 4:[2, 3, 4], 5: function() {}}
var obj = Object.getPrototypeOf(source2)
var target = Object.assign({}, Object.create(obj), source2)
target['0'] = 5
target['3'].name = 'anpoly'
target['4'][0] = 6
console.log(source2)
// {0: 1, 1: null, 2: undefined, 3: {name: "anpoly", age: undefined, sex: null}, 4: [6, 3, 4], 5: ƒ ()}
console.log(target)
// {0: 5, 1: null, 2: undefined, 3: {name: "anpoly", age: undefined, sex: null}, 4: [6, 3, 4], 5: ƒ ()}
结论:结果与数组类似,也无法实现对象的深拷贝。
- 对象深拷贝
对象深拷贝:彻底切断了对象内引用类型的引用关系。
方法:JSON.parse()与 JSON.stringify()
var target = JSON.parse(JSON.stringify(source2))
target['0'] = 5
target['3'].name = 'anpoly'
target['4'][0] = 6
console.log(source2) // {0: 1, 1: null, 2: undefined, 3: {name: "anjou", age: undefined, sex: null}, 4: [2, 3, 4], 5:
ƒ ()}
console.log(target) // {0: 1, 1: null, 3: {name: "anpoly", sex: null}, 4: [6, 3, 4]}