美文网首页
javascript的浅复制和深复制

javascript的浅复制和深复制

作者: id被吃 | 来源:发表于2017-10-12 22:51 被阅读9次

    javascript的基本类型包括字符串、数字、布尔、数组、对象、Null、Undefined。基本类型和对象最大的不同在于他们的传值方式:基本类型是按值传递的,但是对象是按引用传值的.
基本类型:

var a = 1;
var b = a;
b = 2;
console.log(a);  //1
console.log(b); //2

从上面的例子可以看出,由于是按值传递,所以改变b的值不会改变a
如果是对象,由于是按引用传值,类似的做法会改变另外一个相关对象的属性,这就是浅复制(新旧对象公用一块内存空间):

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

如果不让原本obj1对象属性,那么就是深复制(新旧对象使用不同内存空间)
简单实现:

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

这种方法可以实现深度复制,但是略显臃肿,而且如果有嵌套对象(有多层对象)实现起来就更麻烦了,比如:

var obj1 = { grade : { math : 100 , Chinese : 90 } };
var obj2 = { grade : obj1.grade };
obj2.grade.math = 120;
console.log(obj1);  // { grade : { math : 120 , Chinese : 90 } };  
var obj2 = { grade : obj1.grade.math , grade : obj1.grade.Chinese }; //这样才能深度复制

深度复制除了上面方法,还可以用其他方法实现

1.ES6的Object.assign

ES6引入了一个Object.assign的新函数,可以把任意个源对象自身的可枚举属性拷贝给目标对象,然后再返回目标对象。不过其进行的是浅复制i,复制的是对象属性的引用
不过,它还是可以实现一层的深度复制,比起前面的手动复制要简单一点,比如

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

2.JSON.stringify+JSON.parse

前面提到了,js的基本类型是按值传递的,那么既然有这样的特性我们完全可以将对象转换成字符串,然后再用parse解析成新对象

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

不过,这个方法还是有缺陷,只有可以转换成JSON格式的对象才可以使用,RegExp对象是无法通过该方法实现深度复制的,函数也无法使用

3.递归拷贝

function deepClone(initalObj,finalObj){
    var obj = finalObj || {};
    for(var i  in initalObj){
        var prop = initalObj[i];
        if(prop === obj)
          continue;
        if(typeof prop === 'object'){
            obj[i] = (prop.constructor === Array) ? [] : {};
            arguments.callee(prop,obj[i]);
        }else{
            obj[i] = prop;
        }
    }
    return obj;
}

4.Object.create(initalObj)

注意和前面递归方法的区别

function deepClone(initalObj,finalObj){
    var obj = finalObj || {};
    for(var i  in initalObj){
        var prop = initalObj[i];
        if(prop === obj)
          continue;
        if(typeof prop === 'object'){
            obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);
            arguments.callee(prop,obj[i]);
        }else{
            obj[i] = prop;
        }
    }
    return obj;
}

5.slice和concat巧妙的方法

实质上这也是浅复制,只不过返回一个浅复制了原数组中的元素的一个新数组

var arr1 = [1, 2, 3, 4],
    arr2 = arr1.slice(0),
    arr3 = arr1.concat();
 
console.log(arr1, arr2, arr3);
arr2[2] = 10;
arr3[2] = 11;
console.log(arr1[2], arr2[2], arr3[2]);
> 1,2,3,4, 1,2,3,4, 1,2,3,4
> 3, 10, 11

console.log( arr1 === arr2 ); //false
console.log( arr1 === arr3 ); //false

又比如:

var array = [1, [1,2,3], {name:"array"}]; 
var array_concat = array.concat();
var array_slice = array.slice(0);
array_concat[1][0] = 5;  //改变array_concat中数组元素的值 
console.log(array[1]); //[5,2,3] 
console.log(array_slice[1]); //[5,2,3] 
array_slice[2].name = "array_slice"; //改变array_slice中对象元素的值 
console.log(array[2].name); //array_slice
console.log(array_concat[2].name); //array_slice

jQuery提供了一个$.extend方法可以做深度复制

var arr1 = [1, 2, [3, 4], {a: 5, b: 6}, 7],
    arr2 = $.extend(true, [], arr1);
console.log(arr1, arr2);
arr2[1] = 10;
console.log(arr1, arr2);

还有一个叫lodash的函数库的_.cloneDeep方法可以实现深度复制

参考:http://www.cnblogs.com/Chen-XiaoJun/p/6217373.html
http://web.jobbole.com/88602/
https://github.com/wengjq/Blog/issues/3

相关文章

  • 浅拷贝和深拷贝

    本文参考:JavaScript中的浅拷贝和深拷贝js 深拷贝 vs 浅拷贝深入剖析 JavaScript 的深复制...

  • JavaScript 浅复制和深复制

    浅复制只会复制第一层的元素,嵌套的元素还是原来的引用。 深复制会每一层都递归复制

  • javascript的浅复制和深复制

    javascript的基本类型包括字符串、数字、布尔、数组、对象、Null、Undefined。基本类型和对象最大...

  • 深拷贝与浅拷贝的理解及常用方法

    深拷贝和浅拷贝的区别 首先深复制和浅复制只针对像 Object, Array 这样的复杂对象的。简单来说,浅复制只...

  • iOS全解11:特殊问题

    1、浅拷贝和深拷贝的区别? 浅拷贝:只复制指向对象的指针,指针指向同一个地址,而不复制引用对象本身。深拷贝:复制引...

  • java 对象的拷贝

    拷贝:即复制 对象拷贝:即对象复制 java 对象拷贝分类:浅拷贝、深拷贝 java 对象的浅拷贝和深拷贝针对包含...

  • 如何实现数组的深拷贝和浅拷贝?

    1.背景介绍 1.深复制和浅复制 在JavaScript中,对于Object和Array这类引用类型值,他的复制有...

  • 拷贝与内存管理

    一、关于深拷贝和浅拷贝的总结 理解 本质上我认为区别在于复制是是指针复制(浅拷贝)还是复制到新的地址上(深拷贝) ...

  • Javascript对象的深浅拷贝

    开门见山,有人叫对象的复制为深复制浅复制,也有人叫深拷贝浅拷贝。其实都是copy。 深拷贝(递归复制,复制所有层级...

  • JS深浅拷贝

    浅拷贝 浅拷贝的意思就是只复制引用,而未复制真正的值。 深拷贝 深拷贝就是对目标的完全拷贝,不像浅拷贝那样只是复制...

网友评论

      本文标题:javascript的浅复制和深复制

      本文链接:https://www.haomeiwen.com/subject/nnxayxtx.html