js - 浅拷贝和深拷贝

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

浅拷贝和深拷贝,相信大家都知道区别,但是怎么去实现呢?

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

1. Object.assign

相信这个很多人都用过,用过就知道,这个在微信端,ie11或更低版本的ie上并不支持。所以我们就抛弃了这种方法。

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

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

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

通常,浅拷贝只能解决部分问题。所以我们来看看深拷贝。

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

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

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的改变而改变

 

posted @ 2019-01-29 15:56  快饿死的鱼  阅读(389)  评论(0编辑  收藏  举报