前言
“拷贝”,字面意思就是复制,所以 JavaScript 的拷贝就是将一个变量赋值给另外一个变量,在 JavaScript 中有两种拷贝类型 浅拷贝和深拷贝,两者的区别主要体现在引用类型上面
浅拷贝与深拷贝的区别
浅拷贝和深拷贝都是将一个变量赋值给另外一个变量,不同的是,在使用引用类型进行赋值的时候,通过 浅拷贝 赋值的变量会影响到 原始变量 的值,而 深拷贝 则不会。由于引用类型是存储的是地址而非值(可以参考我上一篇文章 JavaScript基础篇-数据类型),所以在修改引用变量的值时是在修改它们存储在堆中的值,但是由于两个变量都是存储的地址,所以两个变量都会发生变化。
// 通过浅拷贝的例子
let obj1 = {
name: 'zhangsan'
}
let obj2 = obj1
obj2.name = 'lisi'
console.log(obj1.name) // lisi
console.log(obj2.name) // lisi
深拷贝的方式(不考虑堆栈溢出)
- JSON转换
主要是使用 JSON 的两个方法 stringify() 和 parse(),先使用 JSON.stringify() 将原有对象转换成 JSON 类型,然后在使用 JSON.parse() 将其转回。该方法存在一定的缺陷:
- 如果对象里有函数,函数无法被拷贝下来
- 无法拷贝对象原型链上的属性和方法
let obj1 = {
name: 'zhangsan'
}
let obj2 = JSON.parse(JSON.stringify(obj1))
obj2.name = 'lisi'
console.log(obj1.name) // lisi
console.log(obj2.name) // zhangsan
- 递归的方式 使用递归的方式把对象中的对象全部遍历完,在遍历中遇到对象就新开辟一块内存进行存储
// 深拷贝
function deepCopy(obj) {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
let result = {};
if (obj instanceof Array) { result = []; }
for(var key in obj) {
// Object的hasOwnProperty()方法返回一个布尔值,判断对象是否包含特定的自身(非继承)属性。
if(obj.hasOwnProperty(key)) { result[key] = deepCopy(obj[key]); }
}
return result;
}
let obj1 = {
name: 'zhangsan'
}
let obj2 = deepCopy(obj1)
obj2.name = 'lisi'
console.log(obj1.name) // lisi
console.log(obj2.name) // zhangsan