初级前端面试,应该经常被问到JS深拷贝和浅拷贝。在开发过程中也会经常遇到S深拷贝和浅拷贝问题。下面我们简单剖析一下,深拷贝和浅拷贝的区别。这里涉及到栈堆,基本数据类型与引用数据类型,不在过多赘述了,这链接里面有关数据类型的简单讲述。
浅拷贝:例如 有一个对象 A,此时 对象 B 等于 A, A 对象新增属性或者修改属性值,此时B也会被响应的修改,B被A对象影响,反之B修改,A也会被修改,相互影响。
var A = {
name: 'A'
}
var B = A;
console.log(A); // {name: "A"}
console.log(B); // {name: "A"}
可以看到B成功复制了A对象, 此时大家相安无事。继续改变A对象的属性值。
A.name = 'AD钙奶';
console.log(A); // {name: "AD钙奶"}
console.log(B); // {name: "AD钙奶"}
可以看到A对象修改,随之B对象也被修改了,反之B修改,A也会被修改,相互影响
深拷贝:与上面示例相反,A对象修改,B对象不被影响,互不打扰。
一、浅拷贝
简单对象赋值、Object.assign、数组 slice 方法、扩展运算符 …
slice方法
var arr = [1,2,[3,4]];
newArr = arr.slice();
console.log(arr); // [1 , 2, [3, 4]]
console.log(newArr); // [1 , 2, [3, 4]]
运行完上述代码,再次执行下面代码 ,修改原始数组 arr[2][0] = 33;发现newArr也同样被修改了
arr[2][0] = 33; // 修改数组里面的值
console.log(arr); // [1 , 2, [33, 4]]
console.log(newArr); // [1 , 2, [33, 4]]
Object.assign
var obj = {name: 'tom'};
obj_a = {age: 12, data:{name: 'jim'}};
Object.assign(obj,obj_a);
console.log(obj); // {name: "tom", age: 12, data: {name: 'jim'}}
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200403084956117.jpg)
再次修改 obj_a.data.name = ‘blue’; obj对象里面 data对象里面的name属性变成了blue;
obj_a.data.name = 'blue';
console.log(obj); // {name: "tom", age: 12, data: {name: 'blue'}}
二、深拷贝
JSON.parse(JSON.stringify())
此方法代码简洁,但是拷贝对象需要遵循 JSON格式,并且函数不能被拷贝
递归克隆对象或数组
// 迭代递归法:深拷贝对象与数组
function deepClone(obj) {
if (Object.prototype.toString.call(obj) !=="[object Object]") {
throw new Error('obj 不是一个对象!')
}
// 判断传进来的是对象还是数组
let isArray = Array.isArray(obj)
let cloneObj = isArray ? [] : {}
// 通过for...in来拷贝
for (let key in obj) {
cloneObj[key] = Object.prototype.toString.call(obj[key]) ==="[object Object]" ? deepClone(obj[key]) : obj[key]
}
return cloneObj
}
var obj = {name:1,age:123,d:{age: 111}};
let cloneObj= deepClone(obj);
console.log(cloneObj) // {name:1,age:123,d:{age: 111}};
三、React项目推荐使用 immutable.js 中文文档
immutable.js 中文文档地址
大家有时间的话,可以点击这里查看另一篇文章深入学习一下,但是文章讲的Object.assign() 可以深拷贝,这个地方是不对的。