深拷贝和浅拷贝 小理解

182 阅读1分钟

浅拷贝:意思就是只复制引用地址(指针),而未复制真正的值 深拷贝:目标的完全拷贝(只要进行了深拷贝,它们老死不相往来,谁也不会影响谁) 深拷贝实现的3种常用的方法:

(1)递归去复制所有层级属性

a.

function deepClone(source) {
    const targetObj = source.constructor === Array ? [] : {}; // 判断复制的目标是数组还是对象
    for (let keys in source) { // 遍历目标
        if (source.hasOwnProperty(keys)) {
            if (source[keys] && typeof source[keys] === 'object') { // 如果值是对象,就递归一下
                targetObj[keys] = source[keys].constructor === Array ? [] : {};
                targetObj[keys] = deepClone(source[keys]);
            } else { // 如果不是,就直接赋值
                targetObj[keys] = source[keys];
            }
        }
    }
    return targetObj;
}

const obj1 = {
    name: 'axuebin',
    sayHello: function () {
        console.log('Hello World');
    }
}
const obj2 = deepClone(obj1);
const obj3 = obj1;
console.log(obj2); // {name: "axuebin", sayHello: ƒ}
console.log(obj1 === obj2); // false
console.log(obj1 === obj3); // true*/

b.

function extend(parent) {
    let child;
    if (Object.prototype.toString.call(parent) == '[object Object]') {
        child = {};
        for (let key in parent) {
            child[key] = extend(parent[key])
        }
    } else if (Object.prototype.toString.call(parent) == '[object Array]') {
        child = parent.map(item => extend(item));
    } else {
        return parent;
    }
    return child;
}

function extendDeep(parent, child) {
    child = child || {};
    for (var key in parent) {
        if (typeof parent[key] === "object") {
            child[key] = (Object.prototype.toString.call(parent[key]) === "[object Array]") ? [] : {};
            extendDeep(parent[key], child[key]);
        } else {
            child[key] = parent[key];
        }
    }
    return child;
}
var obj1 = {
    age: 5,
    hobby: [1, 2, 3],
    home: {city: '北京'},
};

var obj2 = extendDeep(obj1);
console.log(obj1===obj2);//false

注:slice方法不是真正的深拷贝

let a = [0,1,[2,3],4]
let b = a.slice()
a[0] = 1
a[2][0] = 1  // [1,1,[1,3],4]
b   //[0,1,[1,3],4]

深拷贝过后两个是独立的,改变任何一个都不能改变另外一个。

(2)用JSON对象的parse和stringify

const obj3 = {
    name:'axuebin',
    sayHello:function(){
        console.log('Hello World');
    }
}
console.log(JSON.parse(JSON.stringify(obj3)); // {name: "axuebin"} ???
// undefined、function、symbol 会在转换过程中被忽略,所以就不能用这个方法进行深拷贝

(3)JQ的extend方法

$.extend([deep ], target, object1 [, objectN ])
// deep表示是否深拷贝,为true为深拷贝;为false,为浅拷贝。
// target Object类型 目标对象,其他对象的成员属性将被附加到该对象上。
// object1  objectN可选。 Object类型 第一个以及第N个被合并的对象。
例:
let a = [0,1,[2,3],4]
let b = $.extend(true, [], a)
a[0] = 1
a[2][0] = 1  // [1,1,[1,3],4]
b  // [0,1,[2,3],4]