談談我對深拷貝和淺拷貝的理解

yaoer1994發表於2018-04-19

淺拷貝只拷貝一層,深拷貝是層層遞迴拷貝。

詳細點講,就是在進行淺拷貝的時候,被拷貝的物件(稱作P物件)的子屬性A也是一個物件,那麼因為淺拷貝只拷貝了一層,所以拷貝後返回的新物件(稱作S物件)的子屬性A其實和P物件的子屬性A仍然聯絡在一起的,如果對P物件的子屬性A重新賦值,不會影響S物件的子屬性A,但是當只是給P物件的子屬性A的子屬性賦值的時候,那麼S屬性的子屬性A的子屬性的值也會被改變。而因為深拷貝進行了遞迴,所以就不會存在這個問題。

這個解釋。。。。有點繞啊????那麼請看栗子

舉個栗子 (淺拷貝)

    function shallowCopy(src) {
        var dst = {};
        for (var prop in src) {
            if (src.hasOwnProperty(prop)) {
                dst[prop] = src[prop];
            }
        }
        return dst;
    }

    var a = {
        key1: "111",
        key2: ['222', '333']
    }
    a.key3 = ['444', '555'];
    var b = shallowCopy(a);
    b.key2 = ['666', '777'];
    a.key3[0] = '888'
    console.log(a.key2) // ['222', '333']
    console.log(b.key2) // ['666', '777']
    console.log(a.key3) // ['888', '555']
    console.log(b.key3) // ['888', '555']
複製程式碼

下面關於深拷貝的方法是從 司徒正美 的avalon裡面找到的(出處)

再舉個栗子(深拷貝)

    function deepCopy() {
        var options, name, src, copy, copyIsArray, clone,
            target = arguments[0] || {},
            i = 1,
            length = arguments.length,
            deep = false
        var isPlainObject = function (obj) {
            return Object.prototype.toString.call(obj) === "[object Object]" && Object.getPrototypeOf(obj) === Object.prototype
        }
        if (typeof target === "boolean") {
            deep = target
            target = arguments[1] || {}
            i++
        }
        if (typeof target !== "object" && !this.isFunction(target)) {
            target = {}
        }
        if (i === length) {
            target = this
            i--;
        }

        for (; i < length; i++) {
            if ((options = arguments[i]) != null) {
                for (name in options) {
                    src = target[name]
                    copy = options[name]
                    if (target === copy) {
                        continue
                    }
                    if (deep && copy && (isPlainObject(copy) || (copyIsArray = Array.isArray(copy)))) {
                        if (copyIsArray) {
                            copyIsArray = false
                            clone = src && Array.isArray(src) ? src : []
                        } else {
                            clone = src && isPlainObject(src) ? src : {}
                        }
                        target[name] = arguments.callee(deep, clone, copy);
                    } else if (copy !== void 0) {
                        target[name] = copy
                    }
                }
            }
        }
        return target
    }

    var a = {
        key1: "111",
        key2: ['222', '333']
    }
    a.key3 = ['444', '555'];
    var b = deepCopy(true, {}, a);
    b.key2 = ['666', '777'];
    a.key3[0] = '888'
    console.log(a.key2) // ['222', '333']
    console.log(b.key2) // ['666', '777']
    console.log(a.key3) // ['888', '555']
    console.log(b.key3) // ['444', '555']

複製程式碼

現在懂了沒?你懂沒懂沒關係,反正我懂了,哈哈。

相關文章