举个例子来说明一下什么是浅拷贝什么是深拷贝

浅拷贝

var x = {
    a: 1,
    b: {f: {
        g: 1
    }},
    c: [1, 2, 3]
};
var y = shallow(x);

得出的结果可以看出是浅拷贝

  • 非对象的属性值一个改变不影响另一个的值
  • 对象属性是引用赋值所以一个改变会影响另一个的改变

出现这种情况的本质是:对象是按引用赋值的
image

深拷贝

指的是拷贝一个对象,改变一个值不影响另一个的值

// 实现深复制功能
// 判断:1.是否是对象 2.是否是函数
function deepCopy (obj, isDeep) {
    if (!_.isObject(obj)) {
        return obj
    } else {
        if (_.isFunction(obj)) {
            return new Function("return " + obj.toString())();
        } else {
            var name,
                target = _.isArray(obj) ? [] : {},
                value;
            for (name in obj) {
                value = obj[name];

                // 是浅拷贝还是深拷贝
                if (isDeep && (_.isArray(value) || _.isObject(value))) {
                    console.log('深拷贝');
                    target[name] = deepCopy(value, isDeep);
                } else {
                    console.log('浅拷贝');
                    target[name] = value
                }
            }
            return target;
        }
    }
}

var array3 = {
    a: 1,
    b: {f: {
        g: 1
    }},
    c: function () {
        console.log('is function');
    }
};
var array4 = deepCopy(array3, false);

image

一个技巧

使用JSON对象的parse()和stringify()方法

  • pares() JSON字符串转成js对象
  • stringify() 将js对象转成JSON字符串
//例1
var source = { name:"source", child:{ name:"child" } } 
var target = JSON.parse(JSON.stringify(source));
target.name = "target";  //改变target的name属性
console.log(source.name); //source 
console.log(target.name); //target

//例2
var source = { name:function(){console.log(1);}, child:{ name:"child" } } 
var target = JSON.parse(JSON.stringify(source));
console.log(target.name); //undefined

这种方法有局限性:

  • 对于正则表达式类型、函数类型等无法进行深拷贝(而且会直接丢失相应的值)
  • 它会抛弃对象的constructor,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object

参考


Hayley
220 声望9 粉丝

人生因选择而不同,因坚持而精彩