深拷贝和浅拷贝两者的区别:
假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。
用堆(heap)和栈(stack)来说:
浅拷贝是:B拷贝A时,AB指向同一个堆中的值;
深拷贝是:B拷贝A时,B会在堆中开辟出一个新的内存,与A并存。
深拷贝是在堆内存中开辟一个新的内存出来存储数据,是将对象和值复制过来,两个对象间互不影响。
浅拷贝是复制对象有引用地址,两个对象指向同一个地址,一个对象更改时,另一个对象也会更改。
浅拷贝,值的引用
var a = [1, 2, 3, 4, 5];
var b = a;
a[0] = 2
console.log(a);
console.log(b);
//因为b浅拷贝a, ab指向同一个内存地址(堆内存中存的值)
//b会随着a的变化而变化
//[2, 2, 3, 4, 5]
//[2, 2, 3, 4, 5]
深拷贝,两都互不影响:
function clone(source) {
var target = {};
for(var i in source) {
if (source.hasOwnProperty(i)) {
//Object的hasOwnProperty()方法返回一个布尔值,判断对象是否包含特定的自身(非继承)属性。
//hasOwnProperty()这个方法会查找一个对象是否有某个属性,但是不会去查找它的原型链,来自:https://blog.csdn.net/i_dont_know_a/article/details/84324051
//简单来说hasOwnProperty()就是判断自身属性是否存在原型(返回false)中还是实例(返回true)中
target[i] = source[i];
}
}
return target;
}
var obj = {a:1,b:2}
var obj2 = clone(obj)
obj2.a = 2
// obj2 {a: 2, b: 2}
// obj {a: 1, b: 2}
以上的两个实例只是对单层数据格式的实现
递归的方式实现深拷贝:
function clone(source) {
var target = {};
for(var i in source) {
if (source.hasOwnProperty(i)) {
if (typeof source[i] === 'object') {
target[i] = clone(source[i]); // 注意这里
} else {
target[i] = source[i];
}
}
}
return target;
}
var obj = {a:1,b:2,c:3}
var obj2 = clone(obj)
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{};
// Array.isArray() 方法用于判断一个对象是否为数组。
if(obj && typeof obj==="object"){
for(key in obj){
if(obj.hasOwnProperty(key)){
//判断obj子元素是否为对象,如果是,递归复制
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);
JSON对象的stringify和parse实现深拷贝(缺点:无法复制函数类型):
function deepClone(obj){
let _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone
}
let a=[0,1,[2,3],4],
b=deepClone(a);
a[0]=1;
a[2][0]=1;
console.log(a,b);
a 输出 [1,1,[1,3],4]
b 输出 [0,1,[2,3],4]
JQuery的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);
a 输出 [1,1,[1,3],4]
b 输出 [0,1,[2,3],4]
参考自:https://blog.csdn.net/HiSen_CSDN/article/details/103188104