浅拷贝和深拷贝
浅拷贝 vs 深拷贝
- 浅拷贝:创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝,如果属性是基本类型,拷贝该基本类型的值,如果属性是引用类型,拷贝该引用类型的内存地址。
如果一个对象改变了这个地址, 就会影响到另一个对象。 - 深拷贝:将一个对象从内存中完整拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且
修改新对象不会影响原对象。
赋值
// 对象赋值
let obj1 = {
name : 'A',
arr : [1,[2,3],4],
}
let obj2 = obj1
obj2.name = "B"
obj2.arr[1] = [5,6,7]
console.log('obj1',obj1)
console.log('obj2',obj2)
浅拷贝
// 浅拷贝
let obj1 = {
name : 'A',
arr : [1,[2,3],4],
}
let obj3 = shallowClone(obj1)
obj3.name = "B"
obj3.arr[1] = [5,6,7]
// 这是个浅拷贝的方法
function shallowClone(source) {
var target = {}
for (var i in source) {
if (source.hasOwnProperty(i)) {
target[i] = source[i]
}
}
return target
}
console.log('obj1',obj1)
console.log('obj3',obj3)
深拷贝
let obj1 = {
name: 'A',
arr: [1,[2,3],4],
};
let obj4 = deepClone(obj1);
obj4.name = "B";
obj4.arr[1] = [5,6,7];
function deepClone(obj) {
if (obj === null) return obj;
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
if (typeof obj !== "object") return obj;
let cloneObj = new obj.constructor();
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
cloneObj[key] = deepClone(obj[key]);
}
}
return cloneObj;
}
console.log('obj1',obj1);
console.log('obj4',obj4);
浅拷贝的实现方式
- Object.assign():把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。
let obj1 = { person: {name: "Messi", age: 33}, club: 'Barcelona' }
let obj2 = Object.assign({}, obj1)
obj2.person.name = "Suarez"
obj2.club = 'Atlético Madrid'
console.log(obj1)
- 函数库lodash的_.clone方法
var _ = require('lodash')
var obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3]
}
var obj2 = _.clone(obj1)
console.log(obj1.b.f === obj2.b.f)
- 展开运算符...
let obj1 = { name: 'Messi', address:{ x: 100, y: 100 } }
let obj2 = {... obj1}
obj1.address.x = 200
obj1.name = 'Suarez'
console.log('obj2', obj2)
- Array.prototype.concat()
let arr = [ 1, 3, { username: 'Messi' } ]
let arr2 = arr.concat()
arr2[2].username = 'Suarez'
console.log(arr)
- Array.prototype.slice()
let arr = [1, 3, { username: 'Messi' } ]
let arr3 = arr.slice()
arr3[2].username = 'Suarez'
console.log(arr)
深拷贝的实现方式
- JSON.parse(JSON.stringify()): 利用JSON.stringify将对象转成JSON字符串, 再用JSON.parse把字符串解析成对象, 一去一来, 新的对象产生了, 而且对象会开辟新的栈, 实现深拷贝(不能处理函数和正则)
let arr1 = [1, 3, { username: 'Messi' }, function(){} ]
let arr2 = JSON.parse(JSON.stringify(arr1))
arr2[2].username = 'Suarez'
- 函数库lodash的_.cloneDeep方法
var _ = require('lodash')
var obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3]
}
var obj2 = _.cloneDeep(obj1)
console.log(obj1.b.f === obj2.b.f)
- jQuery.extend()方法
$.extend(deepCopy, target, object1, [objectN])