js - 浅拷贝和深拷贝

在项目中,常常会用到拷贝。es6

浅拷贝和深拷贝,相信你们都知道区别,可是怎么去实现呢?微信

我会分享一些项目中常常会用到的一些方法,而后再手写一个深/浅拷贝的方法。dom

1. Object.assign函数

相信这个不少人都用过,用过就知道,这个在微信端,ie11或更低版本的ie上并不支持。因此咱们就抛弃了这种方法。测试

这种方法也只是浅拷贝,不能知足深拷贝的需求spa

2. 经过es6的扩展运算符...来实现浅拷贝code

let a = {
  age: 1
}
let b = { ...a }
a.age = 2
console.log(b.age) // 1

一般,浅拷贝只能解决部分问题。因此咱们来看看深拷贝。对象

3. JSON.parse(JSON.stringify(object))blog

这个方法在项目中用的挺多的。原型链

let a = {
  age: 1,
  jobs: {
    first: 'FE'
  }
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'native'
console.log(b.jobs.first) // FE

可是该方法有局限性:

  • 会忽略 undefined
  • 会忽略 symbol
  • 不能序列化函数
  • 不能解决循环引用的对象

本身实现一个深拷贝是很困难的,由于有不少便捷状况须要考虑。好比原型链,dom如何处理。因此我是根据项目实现的一个简易版的深、浅拷贝。

推荐一个库: lodash

 

    var isObject = function(obj) {
        return obj !== null && (typeof obj === "object" || typeof obj === "function")
    };

    var clone = function(obj, deep) {
        if (!isObject(obj)) {
            throw new Error(obj + " is not object");
        }
        var newObj;
        var cloneArray = function(item) {
            var newItem = [];
            var size = item.length;
            for (var i = 0; i < size; i++) {
                var vk = item[i];
                if (deep && isObject(vk)) {
                    newItem[i] = clone(vk, deep);
                } else {
                    newItem[i] = vk;
                }
            }
            return newItem;
        };
        var cloneObject = function(item) {
            var newItem = {};
            Object.keys(item).forEach(function(n) {
                var v = item[n];
                if (deep && isObject(v)) {
                    newItem[n] = clone(v, deep);
                } else {
                    newItem[n] = v;
                }
            });
            return newItem;
        };
        if (obj instanceof Array) {
            newObj = cloneArray(obj);
            return newObj;
        }

        newObj = cloneObject(obj);
        return newObj;
    }

 

测试代码:

    var obj1 = {
        a: 1,
        b: ["a", "b"]
    };
    var obj2 = {
        b: 2,
        c: obj1
    };
    var obj3 = clone(obj2, true);
    var obj4 = clone(obj2, false);
    obj1.b = ["a", "b", "c"];
    obj1.a = "2";
    console.log(obj3);
    console.log(obj4);

输出结果:

 

 从结果能够看出:

深拷贝obj3的结果不会由于引用类型obj1的改变而改变

浅拷贝obj4的结果会由于引用类型obj1的改变而改变

相关文章
相关标签/搜索