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

相關文章
相關標籤/搜索