前言
在咱们日常开发过程中,常遇到这种场景,在拿到一份数据后,你打算对它进行解决,然而你不想在原先的根底上进行扭转而是心愿拷贝一份正本进去,不便对数据比拟和当前复原数据。
那么这就波及到了 JS 中对数据的深浅拷贝问题。
咱们晓得 JS 中的数据类型可分为两种,根本数据类型(7 种)和援用数据类型(2 种),根本数据类型是保留在栈的数据结构中的,是按值拜访,所以不存在深浅拷贝问题。
而比方对象,数组,函数,正则,工夫对象这些都是援用数据类型,是保留在堆中的。
所以,援用数据类型的复制,是内存地址的传递,并没有拷贝出一份新的数据。
先来看两个概念深拷贝和浅拷贝的区别:
下面说过,首先深拷贝和浅拷贝是只针对 Object 和 Array 这样的援用数据类型的。
浅拷贝:遍历对象中的内容,一个一个的进行赋值,这样只进行一层拷贝的形式了,就是浅拷贝。
深拷贝:不仅将原对象的各个属性一一复制进来,而且将原对象各个属性所蕴含的对象也顺次采纳深复制的办法递归复制到新对象上。
而检测是否深浅拷贝的办法是:
由 obj1 拷贝得 obj2,批改 obj2 外面的对象或者数组的值,obj1 里的象或者数组值发生变化叫 浅拷贝,反之叫深拷贝。
那么 js 有哪些办法实现对象的拷贝呢?
罕用的办法有如下几种:
①、JSON.parse(JSON.stringify(obj))办法(深拷贝)
②、Object.assign()办法(浅拷贝)
③、应用递归办法(深拷贝)
④、Jquery 的 $.extend([deep], target, object1 [, objectN] )办法(deep:true 深拷贝,deep:false 浅拷贝)
上面用具体的代码来阐明每个办法实现拷贝性能的用法以及深、浅拷贝的区别。
留神:在应用 $.extend 办法时须要先引入 <script src=”https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.js”></script>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.js"></script>
<script>
var Person = function() {
return {
basicMessage:{name:'zhangsan',},
hobby:['coding'],
firstName:'zhang'
}
}
//--------------------------------------------- 办法一 ----------------------------------------------------------//
// ①、JSON.parse(JSON.stringify(obj))办法(深拷贝)var person = Person();
var person_1_deep = JSON.parse(JSON.stringify(person));
person_1_deep.firstName = 'Li'; // 字符窜类型
person_1_deep.basicMessage.name = 'LiSi'; // 对象类型
person_1_deep.hobby.push('sleepping');
console.log("%cJSON.parse(JSON.stringify(obj))办法(深拷贝):","background:rgba(252,234,187,1)");
console.log(person);
//--------------------------------------------- 办法二 ----------------------------------------------------------//
// ②、Object.assign()办法(浅拷贝)
var person = Person();
var person_2_deep = Object.assign({},person);
person_2_deep.firstName = 'Li'; // 字符窜类型
person_2_deep.basicMessage.name = 'LiSi'; // 对象类型
person_2_deep.hobby.push('sleepping');
console.log("%cObject.assign()办法(浅拷贝):","background:rgba(252,234,187,1)");
console.log(person);
//--------------------------------------------- 办法三 ----------------------------------------------------------//
// ③、应用递归办法(深拷贝)function copy(source) {
let target;
if (typeof source ==='object') {target = Array.isArray(source)?[]:{};
for(let key in source){if (source.hasOwnProperty(key)) {if (typeof source[key] !=='object') {target[key] = source[key];
} else {target[key] = copy(source[key]); // 递归解决对象
}
}
}
} else {target = source;}
return target;
}
var person = Person();
var person_3_deep = copy(person);
person_3_deep.firstName = 'Li'; // 字符窜类型
person_3_deep.basicMessage.name = 'LiSi'; // 对象类型
person_3_deep.hobby.push('sleepping');
console.log("%c 手写递归(深拷贝):","background:rgba(252,234,187,1)");
console.log(person);
//--------------------------------------------- 办法四 ----------------------------------------------------------//
// ④、Jquery 的 $.extend([deep], target, object1 [, objectN] )办法(deep:true 深拷贝,deep:false 浅拷贝)// 深拷贝
var person = Person();
var person_4_deep = $.extend(true,{},person);
person_4_deep.firstName = 'Li'; // 字符窜类型
person_4_deep.basicMessage.name = 'LiSi'; // 对象类型
person_4_deep.hobby.push('sleepping');
console.log("%c$.extend(深拷贝):","background:rgba(252,234,187,1)");
console.log(person);
// 浅拷贝
var person = Person();
var person_4_shallow = $.extend(false,{},person);
person_4_shallow.firstName = 'Li'; // 字符窜类型
person_4_shallow.basicMessage.name = 'LiSi'; // 对象类型
person_4_shallow.hobby.push('sleepping');
console.log("%c$.extend(浅拷贝):","background:rgba(252,234,187,1)");
console.log(person);
</script>
四种办法打印出的后果以及深浅拷贝比照如下:
打印出后果后置信大家对深浅拷贝的区别曾经高深莫测:
在每种办法外面对拷贝后的数据做了同样的批改,批改了拷贝后数据的数组和对象的值,
在浅拷贝中原来数据的数组或对象产生了扭转,而在深拷贝中原数据一点不变。
上述代码地址请拜访:https://github.com/tianshilia…