js对象深拷贝浅拷贝

对象的深拷贝于浅拷贝

对于基本类型,浅拷贝过程就是对值的复制,这个过程会开辟出一个新的内存空间,将值复制到新的内存空间。而对于引用类型来书,浅拷贝过程就是对指针的复制,这个过程并没有开辟新的堆内存空间,只是将指向该内存的地址进行了复制。然而对引用类型的浅拷贝会出现一个问题,那就是修改其中一个对象的属性,则另一个对象的属性也会改变。产生了问题那必然有相对解决的方法, 就这样深拷贝就开始入场了,深拷贝会开辟新的栈,两个对象对应两个不同的地址,这样一来,改一个对象的属性,也不会改变另一个对象的属性。
下面我们用代码看一下深拷贝于浅拷贝是如何实现的 :

对象的浅拷贝

对象的浅拷贝实现方法很简单,说白了就是一个for in 循环的事情 :

let obj = {
    nNum : 1,
    sName : 'aaron'
};

function shallowCopy(args) {

    let result = {};

    for(let item in args) {
        if(args.hasOwnProperty(item)) {
            result[item] = args[item];
        };
    };

    return result;
};

shallowCopy(obj);

或者,我们可以使用最常见的jQuery来实现这个功能 :

$.extend({} , obj);

亦或者,我们也可以采用ES6的方法用一行代码实现相同的功能 :

Object.assign({} , obj);

对于浅拷贝就说到这了,如果有补充或者发现问题的大牛可以回复我或者邮件通知,我会第一时间进行回复,好了废话说多了,我们接下来看一下深拷贝

对象的深拷贝

如果我们把上面的obj稍微修改一下那浅拷贝就有心无力了 :

let obj = {
    nNum : 1,
    oAar : [1,2,3,4]
};

我们不妨可以再用上面的方法试一下

let newObj = shallowCopy(obj);

newObj === obj      // false
newObj.oAar === obj.oAar   // true

从上面的结果显示我们可以看出,newObj.oAar与obj.oAar指针所指的是同一个位置,那我们如何改正这个问题呢?

其实也很容易,我们将obj.oAar再看待为一个新的对象,对其再进行一次浅拷贝不就可以了吗??不说了,上代码

function deepCopy(args) {

    let result = {};

    for(let item in args){
         if(typeof args[item] === 'object' && args[item] !== null){
             result[item] = deepCopy(args[item]);
         }else{
             result[item] = args[item];
         };
     };

    return result;
};

result(obj);

我们来验证一下

let newObj = result(obj);

newObj === obj      // false
newObj.oAar === obj.oAar   // false

结果也显示我们实现了,ok

但是有没有其他的方式呢,比如说更简洁一些的,也是有的:

我们可以使用jQuery的$.extend(true, {}, obj),同样也可以实现,是不是觉得眼熟。前面我们说浅拷贝的时候也说过这个方法,但是多了一个为true的参数,$.extend()方法,第一个参数默认为false,当设置它为true时则会开启深拷贝模式。

想想还有没有什么其他的方式= ̄ω ̄=?

其实还有一个捷径可走

还是上面举的那个obj,我们对它再进行一次尝试

 let obj = {
    nNum : 1,
    oAar : [1,2,3,4]
 };

 function deepCopy(args) {
      let result = {};

      try {
          result = JSON.parse(JSON.stringify(args));
      }

      return result;
  }

 let newObj = deepCopy(obj);

 newObj === obj      // false
 newObj.oAar === obj.oAar   // false

ヾ(?`Д′?) 什么鬼,这样也行? 那还前面说那么多废话,直接上这个方法岂不是爽歪歪?

但是这里不得不说明一点,投机取巧往往能达到看似相同的结果,但是还是存在一些隐性的问题的

就如上面这种方式和递归的方法相比是有弊端的,比如它会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。

这种方法能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象,即那些能够被 json 直接表示的数据结构。RegExp对象是无法通过这种方式深拷贝。

最后再说一种方法,可以使用Object.create()方法达到深拷贝的效果

function deepCopy(args) {
    let result = {};

    for(let item in args){
           if(typeof args[item] === 'object' && args[item] !== null){
               result[item] = args[item].constructor === Array ? [] :
               Object.create(prop);
           }else{
               result[item] = args[item];
           };
     };

    return result;
}

let newObj = deepCopy(obj);

newObj === obj      // false
newObj.oAar === obj.oAar   // false

好了,更多的第三方库的方法我们就不一一列举了,原理更重要嘛,对吧。

最后我们来总结一下:

浅拷贝我们说了3种方法 :

  • 通过for...in循环来实现
  • 通过Object.assign()方法来实现
  • 通过jQuery中的$.extend()方法来实现

深拷贝我们同样说了四种方法 :

  • 通过递归的手法实现
  • 通过jQuery中的$.extend()添加true参数方法来实现
  • 通过JSON序列化反序列化来实现
  • 用过Object.create()方法来实现

除了这几种如果各位还想到了其他什么好的方法欢迎下方留言ヾ( ̄▽ ̄)

原文地址:https://www.cnblogs.com/AaronShen/p/8406015.html

时间: 2024-08-15 06:01:38

js对象深拷贝浅拷贝的相关文章

4个方面彻底说清JS的深拷贝/浅拷贝

首先,本文适用于业务需要,急需知道如何深拷贝JS对象的开发者.第二类,希望扎实JS基础,将来好去面试官前秀操作的好学者. 第一类 你只需要一行黑科技代码就可以实现深拷贝 var copyObj = { name: 'ziwei', arr : [1,2,3] } var targetObj = JSON.parse(JSON.stringify(copyObj)) 此时 copyObj.arr !== targetObj.arr 已经实现了深拷贝 别着急走,利用window.JSON的方法做深拷

js对象的浅拷贝与深拷贝

浅拷贝和深拷贝都是对于JS中的引用类型而言的,浅拷贝就只是复制对象的引用(堆和栈的关系,原始(基本)类型Undefined,Null,Boolean,Number和String是存入堆,直接引用,object array 则是存入桟中,只用一个指针来引用值,如果拷贝后的对象发生变化,原对象也会发生变化.只有深拷贝才是真正地对对象的拷贝. 1.浅拷贝 默认是浅拷贝,只是将地址进行了复制,示例如下: //浅拷贝 var obj1={name:"cat"}; var obj2=obj1; o

js对象深拷贝

由于引用类型(数组.对象)是按地址传递,直接拷贝是浅拷贝,即修改拷贝后的变量,原变量也会改变.有时需要深拷贝一个对象,这时就需要遍历彻底复制,使原对象和拷贝对象完全脱离关系. 代码: function deepCloneObj(obj){ var i; var o = Array.isArray(obj) ? [] : {}; for(i in obj){ if(obj.hasOwnProperty(i)){ o[i] = typeof obj[i] === "Object"? dee

JS对象的浅拷贝与深度拷贝

1.js中的6个标准类型 原始类型:Undefined.Null.Boolean.String.Number 引用类型:Object ( 最简单的引用类型var obj={} ) 2.把标准类型分成了两类.这两种类型复制克隆有很大区别 原始类型:存储的是对象的实际数据( 存放在栈内存中 ) 引用类型:存储的是对象的引用地址( 栈内存中存放的堆内存的地址 ) 3.克隆概念 浅度克隆:原始类型为值传递.对象类型仍为引用传递 深度克隆:所有的元素与属性均完全复制.与原对象完全脱离关系( 对新对象的修改

js 对象深拷贝

/* *p需要拷贝的对象 * */ var deepCopy=function(p, c) { var c = c || {}; for (var i in p) { if (typeof p[i] === 'object') { c[i] = (p[i].constructor === Array) ? [] : {}; deepCopy(p[i], c[i]); } else { c[i] = p[i]; } } return c; }

js对象浅拷贝和深拷贝详解

js对象浅拷贝和深拷贝详解 作者:i10630226 字体:[增加 减小] 类型:转载 时间:2016-09-05我要评论 这篇文章主要为大家详细介绍了JavaScript对象的浅拷贝和深拷贝代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 本文为大家分享了JavaScript对象的浅拷贝和深拷贝代码,供大家参考,具体内容如下 1.浅拷贝 拷贝就是把父对像的属性,全部拷贝给子对象. 下面这个函数,就是在做拷贝: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 var

js中对象的浅拷贝和深拷贝的区别

js中对象的浅拷贝和深拷贝的区别 浅度拷贝:复制一层对象的属性,并不包括对象里面的为引用类型的数据,当改变拷贝的对象里面的引用类型时,源对象也会改变. 深度拷贝:重新开辟一个内存空间,需要递归拷贝对象里的引用,直到子属性都为基本类型.两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性. 数据的类型: 一般数据(值传递):字符,数值,布尔,undefined 拷贝(复制)时,传递的是值,修改新数据,不会影响老数据 复杂数据(引用传递):对象 拷贝(复制)时,传递的是内存地址的

对象的浅拷贝与深拷贝

因为JS对象和函数都存在引用的关系,某些时候我们想要直接复制一个对象或者数组什么的,存在引用关系会引起程序发生我们不期望发生的改变,所以需要进行拷贝方法的封装. 浅拷贝,适用于对象深度只有一层,多层的对象要使用深拷贝,把所有层都拷贝出来. function simpleCopy(obj){ //浅拷贝 var newObj = {}; for(var attr in obj){ newObj[attr] = obj[attr]; } return newObj; } 深拷贝,使用了递归的思路,把

JavaScript对象的浅拷贝与深拷贝

1.JS包含两种数据类型: 值类型(基本类型)和引用类型(对象类型) 值类型都是简单的数据段(Number.String .Boolean.Null.Undefined),引用类型是由多个值构成对象(Object .Array .Function .Data等). 我们进行变量赋值时,解析器首先要确认的就是这个值是基本类型还是引用类型. 值类型数据存储在栈(stack)中,栈是内存中一种特殊的数据结构,也称为线性表.变量的位置和变量值的位置是重叠的,也就是说值类型的数据被存储在变量被访问的位置.