网站首页 » 前端开发 » JavaScript » JavaScript 浅拷贝与深拷贝(对象合并)
上一篇:
下一篇:

JavaScript 浅拷贝与深拷贝(对象合并)

在平时的开发中我们经常会用对对象进行合并,简单的合并,比如:用户参数也默认参数的合并。有时候需要更深层次的合并,如复杂对象的合并。而这些合并就会涉及到 JavaScript 中的浅拷贝和深拷贝。浅拷贝的思路和实现也非常的简单,深拷贝相对来说就复杂一些。

浅拷贝

方法一

看过来
// ES6 方法 浅拷贝
var a1 = { a: 1 };
var a2 = { b: 2 };
var a3 = { c: 3 };
var obj = Object.assign(a1, a2, a3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(a1);  // { a: 1, b: 2, c: 3 },
console.log(a2); // { b: 2 }
console.log(a3); // { b: 3 }

这个方法会修改目标对象(如代码中的 a1),所以最好像下面这样写。

可能改成这样
var a1 = { a: 1 };
var a2 = { b: 2 };
var a3 = { c: 3 };
var obj = Object.assign({},a1, a2, a3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(a1);  // { a: 1 },
console.log(a2); // { b: 2 }
console.log(a3); // { b: 3 }

这样就不会污染了其它对象,因为此时你传了一个空对象进去了,所有的属性|属性值,都会拷贝到这个对象里。

方法二

看这里
var a1 = { b: 2 };
var a2 = { c: 3,d:{ccc:5}};
// 合并对象
function extend(target, source) {
    for (var obj in source) {
        target[obj] = source[obj];
    }
    return target;
}

这个方法可以合并两个对象。但有时候我们却需要合并多个对象。下面是一个加强版

加强版
// 浅拷贝
var a1 = { a: 1 };
var a2 = { b: 2 };
var a3 = { c: 3 };
// 合并对象
function extend() {
    var len = arguments.length;
    var target = {};
    for(var i=0;i<len;i++){
        for (var obj in arguments[i]) {
            target[obj] = arguments[i][obj];
        }
    }
    return target;
}
console.log(extend(a1,a2,a3)); // {a: 1, b: 2, c: 3}

理论上是可以合并无数个对象的,这个方法返回的是一个新的对象,所以不会影响到已有对象。

深度拷贝

下面这个方法自己看了好处都没看出来是哪里有问题,想把代码贴出来让大伙看看,下面这段代码为什么无法实现深度拷贝:

请看题
// 深度拷贝
var a1 = { a: 2,b:5,c:{d:1,e:33}};
var a2 = { f: 3};
console.log(extend(a1,a2));
a1.c.d = 888;

function extend() {
    var source,item;
    var target = {};
    var len = arguments.length;
    for(var i=0;i<len;i++){
        item = arguments[i];
        for (var key in item) {
            source = item[key];
            if(getType(source) === "Object"){
                target[key] = extend(source);
            }
            target[key] = source;
        }
    }
    return target;
}

// 获取变量类型
function getType(object){
    /**
    * 方法来源:prototype.js
    * getType(5); // => "Number"
    * getType({}); // => "Object"
    * getType(/foo/); // => "RegExp"
    * getType(''); // => "String"
    * getType(true); // => "Boolean"
    * getType([]); // => "Array"
    * getType(undefined); // => "Window"
    * getType(Element); // => "Constructor"
    **/
    return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
}

上面的实现浅拷贝是没问题的,但是要实现深度拷贝就会有问题,拷贝的对象里的对象还是一个址引用。比如上面的这个例子,先用这个方法把 a1 和 a2 这两个对象合并,然后打印出来,接着就是修改 a1.c.d 的值,结果新拷贝的对象里的对应的值跟着改变了,这是为什么???

  • 微信扫一扫,赏我

  • 支付宝扫一扫,赏我

声明

原创文章,不经本站同意,不得以任何形式转载,如有不便,请多多包涵!

本文永久链接:http://yunkus.com/javascript-object-shallow-copy-and-deep-copy/

发表评论

电子邮件地址不会被公开。 必填项已用*标注

评论 END