JS 深拷贝和浅拷贝
JS 深拷贝和浅拷贝 面试必考题
看了,就要会,不然都是浪费
一、先来看一下下面代码输出什么?
let a=[0,1,2,3,4],
b=a;
console.log(a===b);
a[0]=1;
console.log(a,b);
// [1,1,2,3,4]
// [1,1,2,3,4]
嗯?明明b复制了a,为啥修改数组a,数组b也跟着变了,为什么呢?
课前知识必备( 基本数据与引用数据)
- 基本数据类型:
number,string,boolean,null,undefined,symbol - 引用数据类型:
Object有常规名值对的无序对象{a:1},数组[1,2,3],以及函数function等
二、区别是什么呢? (重点)
基本类型存在栈
stack,应用类型存在堆heap
如下图很好解释了堆栈
-
栈:自动分配内存空间,系统自动释放,里面存放的是基本类型的值和引用类型的地址
-
堆:动态分配的内存,大小不定,也不会自动释放。里面存放引用类型的值。
![image]()
简单来说,就是浅拷贝只是复制了stack 的地址(指向同一个object),深拷贝就是开辟了一个新的内存,来编辑数据
三、怎样可以深拷贝
方法一 、JSON 解析
const data = {a:[1,2,3,4],b:"name"}
const deepclone = JSON.parse(JSON.stringify(res)) // 深拷贝
方法二、使用lodash 库
按需引入
<script src="lodash.js"></script>
import clonedeep from 'lodash.clonedeep'
- 官方文档 https://www.lodashjs.com/docs/lodash.cloneDeep
这个方法类似_.clone,除了它会递归拷贝 value。(注:也叫深拷贝)。
例子:
var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// => false
方法三、除了上面两种方法之外,我们还可以借用JQ的extend方法。
$.extend( [deep ], target, object1 [, objectN ] )
deep表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝
target Object类型 目标对象,其他对象的成员属性将被附加到该对象上。
object1 objectN可选。 Object类型 第一个以及第N个被合并的对象。
let a=[0,1,[2,3],4],
b=$.extend(true,[],a);
a[0]=1;
a[2][0]=1;
console.log(a,b);
方法四、当然还可以自己DIY,写个递归
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{};
if(obj && typeof obj==="object"){
for(key in obj){
if(obj.hasOwnProperty(key)){
//判断ojb子元素是否为对象,如果是,递归复制
if(obj[key]&&typeof obj[key] ==="object"){
objClone[key] = deepClone(obj[key]);
}else{
//如果不是,简单复制
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
let a=[1,2,3,4],
b=deepClone(a);
a[0]=2;
console.log(a,b);
跟之前想象的一样,现在b脱离了a的控制,不再受a影响了。


浙公网安备 33010602011771号