JavaScript深拷贝与浅拷贝的区别

JavaScript深拷贝与浅拷贝的区别

注:深浅拷贝的区别只适用于array【数组】与object【对象】

一、数组Array

1、拷贝情况

  • 浅拷贝:相当于使两个数组指针指向相同的地址,任一个数组元素发生改变,影响另一个。

  • 深拷贝:两数组指针指向不同的地址,数组元素发生改变时不会相互影响。

2、实现

1、浅拷贝:赋值运算符
var a = [1, 2, 3]
    b = a
console.log("a: ",a)
console.log("b: ",b)

b[0] = 99;
console.log("---- after changed array b ----- ")
console.log("a: ",a)
console.log("b: ",b)

运行结果:a数组元素随b数组改变
浅拷贝数组运行结果

2、深拷贝:

方法一:JavaScript的slice函数

var a = [1, 2, 3]
    b = a.slice(0)
console.log("a: ",a)
console.log("b: ",b)

b[0] = 99;
console.log("---- after changed deepClone array b ----- ")
console.log("a: ",a)
console.log("b: ",b)

运行结果:a数组元素未随b数组改变
深拷贝数组运行结果

方法二、JavaScript的concat函数

var a = [1, 2, 3]
    b = a.concat([])
console.log("a: ",a)
console.log("b: ",b)

b[0] = 99;
console.log("---- after changed deepClone array b ----- ")
console.log("a: ",a)
console.log("b: ",b)

运行结果:a数组元素未随b数组改变
数组深拷贝运行结果

方法三、jquery的extend函数

1、一维数组

var a = [1, 2, 3]
    // jQuery.extend([deep], target, object1, object2, object3...),
    // [deep]:默认false【不能显式设置为false;值为true时深度合并对象。
    // target:其他对象复制到该对象
    // object:被合并的对象
    b = $.extend(true, [], a)
console.log("a: ",a)
console.log("b: ",b)

b[0] = 99;
console.log("---- after changed deepClone array b ----- ")
console.log("a: ",a)
console.log("b: ",b)

运行结果:此例中【deep】值为true和false时结果相同
extend函数深拷贝结果

2、二维数组

1、【deep】值为false,对象不进行深度合并

var a = [[1, 2, 3], 4, [5, 6]]
    b = $.extend([], a)
console.log("a: ",a)
console.log("b: ",b)

b[0][0] = 99;
console.log("---- after changed deepClone array b ----- ")
console.log("a: ",a)
console.log("b: ",b)

运行结果:修改前的数组也受到影响,暂不清楚原因
extend浅拷贝二维数组结果

2、【deep】值为true,对象进行深度合并

var a = [[1, 2, 3], 4, [5, 6] ] 
    b = $.extend(true, [], a)
console.log("a: ",a)
console.log("b: ",b)

b[0][0] = 99;
console.log("---- after changed deepClone array b ----- ")
console.log("a: ",a)
console.log("b: ",b)

运行结果:
extend深拷贝二维数组结果

二、对象Object

1、拷贝情况

  • 浅拷贝:只拷贝对象的第一层属性,对于属性中包含的属性不会复制;由于JavaScript对象均以地址的方式存贮,所以浅复制导致多个对象的属性均指向同一块地址。
  • 深拷贝:对对象的每一层属性进行递归复制,深层次的属性也不会指向同一块地址【同一个对象】。

2、实现

1、浅拷贝:

方法一、自定义函数

function shallowCopy(obj1, obj2) {
    for( var key in obj1){
        if (obj1.hasOwnProperty(key)) {
            obj2[key] = obj1[key]
        }
    }
}
function showKeys(obj) {
    for( var key in obj){
        if (obj.hasOwnProperty(key)) {
            console.log(key, ":", obj[key]);
        }
    }
}

var a = {
    sing:true, 
    dance:{today:false, tommorrw:true} 
} 
    b = {}
shallowCopy(a, b)
showKeys(a)
showKeys(b)

b.sing = false
b.dance.today = true
console.log("------------- after changed object b -------------- ")
showKeys(a)
showKeys(b)

运行结果:由于对象的浅拷贝只复制第一层属性,因此obj b第一层属性的改变不会影响复制源,而第二层属性仍指向同一块地址,因此obj b的dance属性的today属性作改变之后,同一块地址处的obj a的dance属性的today属性同时变化了。

对象拷贝结果

方法二、jquery的extend函数:【deep】参数为false

function showKeys(obj) {
    for( var key in obj){
        if (obj.hasOwnProperty(key)) {
            console.log(key, ":", obj[key]);
        }
    }
}

var a = {
    sing:true, 
    dance:{today:false, tommorrw:true} 
} 
    b = $.extend({}, a)

showKeys(a)
showKeys(b)

b.sing = false
b.dance.today = true
console.log("------------- after changed object b -------------- ")
showKeys(a)
showKeys(b)

运行结果:同上
extend函数对象拷贝

2、深拷贝

方法:jquery的extend函数:【deep】参数为true

function showKeys(obj) {
    for( var key in obj){
        if (obj.hasOwnProperty(key)) {
            console.log(key, ":", obj[key]);
        }
    }
}

var a = {
    sing:true, 
    dance:{today:false, tommorrw:true} 
} 
    b = $.extend(true, {}, a)

showKeys(a)
showKeys(b)

b.sing = false
b.dance.today = true
console.log("------------- after changed object b -------------- ")
showKeys(a)
showKeys(b)

运行结果:多层属性深拷贝,互不影响
extend函数对象拷贝

三、实现js基本数据类型的拷贝

实现对object、array、number、boolean、string的值进行复制,其中object和array需要判断,用各自的方法进行复制,其他数据类型可直接复制。

function cloneAll(obj) {
    if (obj instanceof Array) {
        var result = []
        for (var i = 0, max = obj.length; i < max; i++) {
            result[i] = cloneAll(obj[i])
        }
        return result
    }

    else if(obj instanceof Object){
        var result = {}
        for(key in obj){
            result[key] = cloneAll(obj[key])
        }
        return result
    }

    else{
        return obj
    }
}
  • 2
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值