Javascript-深淺拷貝

深淺拷貝簡介

javascript中對於Object和Array這兩個類型,把一個變量賦值給另外一個變量;淺拷貝只是對拷貝對象的引用,深拷貝是完全拷貝,生成一個新的屬性相同的對象javascript

淺拷貝(shallow copy)

淺拷貝只是對拷貝對的引用,二者相互影響 java

淺拷貝的實現

1.簡單賦值實現

例子:obj2拷貝了obj1,obj2改變,obj1也會改變,改變以後2者仍是相同的數組

var obj1 = {a: 1}
    var obj2 = obj1
    obj2.b = 2
    console.log(obj1) // {a: 1, b: 2}
    console.log(obj2) //{a: 1, b: 2}
    console.log(obj1 == obj2) // true

Object.assign()實現

例子:當第一個傳參是你須要拷貝的對象(PS:Object.assign()也能夠實現深拷貝)oop

var obj1 = {a: 1}
    var obj2 = Object.assign(obj1)
    obj2.b = 2
    console.log(obj1) // {a: 1, b: 2}
    console.log(obj2) // {a: 1, b: 2}
    console.log(obj1 == obj2) // true

深拷貝(deep copy)

完全拷貝,生成一個新的屬性相同的對象 this

深拷貝的實現

Object.assign()實現

例子:拷貝對象不是第一個傳參code

var obj1 = {a: 1}
    var obj2 = Object.assign({}, obj1)
    obj2.b = 2
    console.log(obj1) // {a: 1}
    console.log(obj2) // {a: 1, b: 2}
    console.log(obj1 == obj2) // false

Array.slice()能夠實現數組的深拷貝(數組中不能有Object和Array,Object和Array只是淺拷貝)

var arr1 = [1, [2]]
    var arr2 = arr1.slice()
    arr2[1].push(3)
    arr2.push(4)
    console.log(arr1) // [1, [2, 3]]
    console.log(arr2) // [1, [2, 3], 4]
    console.log(arr1 == arr2) // false

JSON.stringify()和JSON.parse()實現

var obj1 = {a: 1}
    var obj2 = JSON.parse(JSON.stringify(obj1))
    console.log(obj1 == obj2) // false
    obj2.b = 2
    console.log(obj1) // {a: 1}
    console.log(obj2) // {a: 1, b: 2}

遞歸實現

var deepCopy = function(obj) {
        if (typeof obj !== 'object') return;
        var newObj = obj instanceof Array ? [] : {};
        for (var key in obj) {
            if (obj.hasOwnProperty(key)) {
                newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
            }
        }
        return newObj;
    }
    var obj1 = {a: 1}
    var obj2 = deepCopy(obj1)
    console.log(obj1 == obj2) // false
    obj2.b = 2
    console.log(obj1) // {a: 1}
    console.log(obj2) // {a: 1, b: 2}

Object.create()實現

var deepCopy = function(obj) {
        if (typeof obj !== 'object') return;
        var newObj = obj instanceof Array ? [] : {};
        for (var key in obj) {
            if (obj.hasOwnProperty(key)) {
                newObj[key] = typeof obj[key] === 'object' ? Object.create(obj[key]) : obj[key];
            }
        }
        return newObj;
    }
    var obj1 = {a: 1}
    var obj2 = deepCopy(obj1)
    console.log(obj1 == obj2) // false
    obj2.b = 2
    console.log(obj1) // {a: 1}
    console.log(obj2) // {a: 1, b: 2}

jQuery.extend()實現

var obj1 = {a: 1}
    var obj2 = $.extend(true, {}, obj1)
    console.log(obj1 == obj2) // false
    obj2.b = 2
    console.log(obj1) // {a: 1}
    console.log(obj2) // {a: 1, b: 2}

jQuery.extend()源碼 對象

jQuery.extend = jQuery.fn.extend = function() {
        var src, copyIsArray, copy, name, options, clone,
            target = arguments[0] || {}, // 默認取第一個參數賦值給target
            i = 1,
            length = arguments.length, // 獲取參數的個數
            deep = false; // 默認淺拷貝

        // Handle a deep copy situation
        if ( typeof target === "boolean" ) { // 若是第一個參數類型爲boolean,那麼把該參數賦值給局部變量deep
            deep = target;  
            target = arguments[1] || {}; // 把第二個參數賦值給target
            // skip the boolean and the target
            i = 2;
        }

        // Handle case when target is a string or something (possible in deep copy)
        if ( typeof target !== "object" && !jQuery.isFunction(target) ) { // target不是object類型或者不是function,就賦值{}
            target = {};
        }

        // extend jQuery itself if only one argument is passed
        if ( length === i ) { // 若是隻有一個參數,這時候i就是1,length也就是1,那麼把target設置爲調用者,也就是jQuery對象自己!同時把i遞減爲0
            target = this; // this就是jQuery
            --i;
        }

        for ( ; i < length; i++ ) { // 循環參數
            // Only deal with non-null/undefined values
            if ( (options = arguments[ i ]) != null ) {
                // Extend the base object
                for ( name in options ) {
                    src = target[ name ]; 
                    copy = options[ name ];

                    // Prevent never-ending loop
                    if ( target === copy ) { // 防止無休止循環
                        continue;
                    }

                    // Recurse if we're merging plain objects or arrays
                    // deep是否深拷貝,copy是參數屬性值
                    if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
                        if ( copyIsArray ) { // 被拷貝的屬性值是數組
                            copyIsArray = false;
                            clone = src && jQuery.isArray(src) ? src : [];
                        } else { // 不是數組
                            clone = src && jQuery.isPlainObject(src) ? src : {};
                        }

                        // Never move original objects, clone them
                        target[ name ] = jQuery.extend( deep, clone, copy );  // 遞歸~

                    // Don't bring in undefined values
                    } else if ( copy !== undefined ) {  // 淺拷貝,且屬性值不爲undefined
                        target[ name ] = copy;
                    }
                }
            }
        }

        // Return the modified object
        return target;
    };

更多方法...敬請期待

相關文章
相關標籤/搜索