浅拷贝
新的对象复制已有对象中非对象属性的值和对象属性的引用。
数组的 slice、concat 、展开运算符… 返回的是浅拷贝的对象。
var a = [ 1, 3, 5, { x: 1 } ];
var b = Array.prototype.slice.call(a);
b[0] = 2;
console.log(a); // [ 1, 3, 5, { x: 1 } ];
console.log(b); // [ 2, 3, 5, { x: 1 } ];
let arr = [1, 2, 3];
let newArr = [...arr]; //同arr.slice()是一样的效果
数组里面嵌套了对象或者数组的话,就会出现不一样的结果。
var a = [ 1, 3, 5, { x: 1 } ];
var b = Array.prototype.slice.call(a);
b[3].x = 2;
console.log(a); // [ 1, 3, 5, { x: 2 } ];
console.log(b); // [ 1, 3, 5, { x: 2 } ];
对象方法Object.assign属于浅拷贝
var a = {x:1, y: {x:2}}; var b = Object.assign({}, a); b.x = 2; b.y.x = 3; console.log(a); //{x:1, y:{x:3}} console.log(b); //{x:2, y:{x:3}}
如果数组元素是基本类型,就会拷贝一份,互不影响;
但是如果是对象数组这样的引用类型的时候拷贝的就是其引用,这样无论在新旧数组进行了修改两者都会发生改变。
浅拷贝实现
var arr = [1,{b:function(){ console.log(2) }}, function(){ console.log(1) },[5,6]]
var shallowCopy = function(obj) {
// 只拷贝对象
if (typeof obj !== 'object') return;
// 根据obj的类型判断是新建一个数组还是对象
var newObj = obj instanceof Array ? [] : {};
// 遍历obj,并且判断是obj的属性才拷贝
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key];
}
}
return newObj;
}
let new_arr = shallowCopy(arr)
new_arr[1].b() // 2 证明浅拷贝成功 包括函数
new_arr[0] // 1
arr[3][1]=111
console.log(new_arr[3][1]) //1111
深拷贝
遍历一个对象中所有的属性的值及对象属性中的属性值,不论是嵌套了几层,要完成所有对象属性的递归后,赋值给一个新的对象。
var a = { x: 1, y: { x: 1 } };
function copy(data) {
var b={};
if (typeof data === 'number') {
return data
}
for (var i in data) {
if (data.hasOwnProperty(i)) {
b[i] = copy(data[i]);
}
}
return b;
}
也可以使用快捷的深拷贝方式,完成对象复制,但是这种方式要求所要复制的对象的属性值是非函数。
var arr = [{name:'xiao'}, [1]] var new_arr = JSON.parse(JSON.stringify(arr)); new_arr[0].name = 'big'; arr[1][0] = 2; console.log(arr) //[{name:'xiao'}, [2]] console.log(new_arr)//[{name:'big'}, [1]]
深拷贝实现
var arr = [1,{b:function(){ console.log(2) }}, function(){ console.log(1) },[5,6]]
var deepCopy = function(obj) {
// 只拷贝对象
if (typeof obj !== 'object') return;
// 根据obj的类型判断是新建一个数组还是对象
var newObj = obj instanceof Array ? [] : {};
// 遍历obj,并且判断是obj的属性才拷贝
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = typeof obj[key] !== 'object'? obj[key] : deepCopy(obj[key]);
}
}
return newObj;
}
let new_arr = deepCopy(arr)
arr[3][1]=111
console.log(new_arr[3][1]) //6 证明深拷贝成功
直接赋值
let arr = [1, 2, 3]; let newArr = arr; newArr[0] = 100; console.log(arr);//[100, 2, 3]
这是直接赋值的情况,不涉及任何拷贝。当改变newArr的时候,由于是同一个引用,arr指向的值也跟着改变。
参考: