浅谈js深拷贝
发布于 5 年前 作者 myfirebug 4489 次浏览 来自 分享

在学习深拷贝之前,我们要先搞清楚js的数据类型,既:值类型引用类型 **值类型:**undefined, string, number, boolean, Symbol **引用类型:**object, function, array 对于基本数据类型来说,它的值直接存储在栈内存中,而对于引用类型来说,它在栈内存中仅仅存储了一个引用,而真正的数据存储在堆内存中 当我们对数据进行操作时,会发现两种情况:

// 值类型
let a1 = 10;
let b1 = a1;
a1 = 11;
console.log(b1);  // 10

对于基本类型来说,我们将一具基本类型的值赋值给a1变量,接着将a1的值赋值给变量b1;然后修改a1,可以看到a1被修改了, b1的值并没有变化,两个变量都使用的独立的数据; 值类型.jpg

// 引用类型
let a2 = {a: 1};
let b2 = a2;
b2.a = 12;
console.log(a2.a); // 12

从结果可以看出两个对象的值全部被修改了 对于引用类型来说,我们将a2赋值给b2时,其实只是将a2的存储在堆中的引用地址赋值给b2,而两个对象此时指向的是在堆内存中的同一条数据,所以当我们修改做任意一个值 的时候,修改的都是堆内存中的数据, 引用类型.jpg

js浅拷贝与深拷贝的区别 简单来说就是假设B复制了A对象,当修改A对象时,看B是否会发生变化,如果B也跟着变化了,说明是浅拷贝,如果B没有变化说明是深拷贝。

深拷贝实现 1.使用JSON.stringify()以及JSON.parse()

let o1 = {
	a: 1,
	b: 1
}
let o2 = JSON.parse(JSON.stringify(o1))
o2.a = 100
console.log(o1.a)  // 1
// 缺点举例
let o1 = {
	a: 1,
	b: null,
	c: false,
	d: '123',
	e: undefined,
	f: function() {alert(123)},
	g: /ss/
}
let o2 = JSON.parse(JSON.stringify(o1))
console.log(o2)

缺点:使用JSON.stringify()以及JSON.parse()它是不可以拷贝 undefined , function, RegExp等类型

2.使用Object.assign(target, source)

let o1 = {
	a: 1,
	b: null,
	c: false,
	d: '123',
	e: undefined,
	f: function() {alert(123)},
	g: /ss/
}
let o2 = Object.assign({}, o1)
o2.a = 1000
console.log(o1.a) // 1
// 缺点举例
let o1 = {
	a: 1,
	b: null,
	c: false,
	d: '123',
	e: undefined,
	f: function() {alert(123)},
	g: /ss/,
	h: {
		a: 1,
		b: 2
	}
}
let o2 = Object.assign({}, o1)
o2.h.a = 1000
console.log(o1.h.a)

缺点:对于一层对象来说是没有任何问题的,但是如果对象的属性对应的是其它的引用类型的话,还是只拷贝了引用,修改的话还是会有问题

3.递归拷贝

let o1 = {
	a: 1,
	b: null,
	c: false,
	d: '123',
	e: undefined,
	f: function() {alert(123)},
	g: /ss/,
	h: {
		a: 1,
		b: 2
	}
}
function deepClone(obj = {}) {
         if (typeof obj !== 'object') {
             // obj不是对象情况直接返回
             return obj;
         }
         // 初始化返回结果
         let result
         if (obj instanceof Array) {
             result = []
         } else {
             result = {}
         }
         
         for (let key in obj) {
             // 保证key不是原型的对象
             if (obj.hasOwnProperty(key)) {
                // 递归
                if (obj[key] && typeof obj[key] === 'object' && obj[key].constructor !== RegExp) {
                    result[key] = deepClone(obj[key])
                } else {
                    result[key] = obj[key]
                }
             }
         }
         //  返回结果
         return result
     }
let o2 = deepClone(o1)
o2.h.a = 123
console.log(o1.h.a) // 1
回到顶部