深浅拷贝

参考:

  JavaScript专题之深浅拷贝。

 

浅拷贝:

  浅拷贝就是拷贝指向对象的指针,因此,如果其中一个对象改变了这个地址,就会影响到另一个对象。

  在 js 中,如果与深拷贝一起提及的话,就意味着只在首层上进行一次完全(资源)复制,如果首层内部存在引用类型的对象,则这个对象仅仅是 copy 了内存地址而已。

  

  常用的浅拷贝以及用法如数组中的 arr.concat()、arrr.slice(), 常规对象中的 Object.assign({},sourceObj)、{...sourceObj} 。

  js 实现起来也简单:

var shallowCopy = function(obj) {
  // 不是对象不 Copy
  if (typeof obj !== 'object') return;
  // 根据obj的类型判断是新建一个数组还是对象
  var newObj = obj instanceof Array ? [] : {};
  // 遍历obj,并且判断是obj的属性才拷贝
  for (var key in obj) {
    if (obj.hasOwnProperty(key)) newObj[key] = obj[key];
  }

  return newObj;
}

 

深拷贝:

  深拷贝就是指完全的拷贝一个对象,即使嵌套了对象,两者也相互分离,修改一个对象的属性,也不会影响另一个。

 

  常用的方法:

  • JSON.parse(JSON.stringify(obj)),不过这个方法有很多缺点:
      1.如果 obj 中包含事件对象,结果中时间将只会以字符串形式出现;
      2.如果 obj 中包含 RegExp、Error对象,则结果中只得到空对象({});
      3.如果 obj 中包含函数、undefined,则结果中会丢弃;
      4.如果 obj 中包含 NaN、Infinity、-Infinity,则结果中会变成 null;
      5.如果对象中存在循环引用,将无法实现正确拷贝;
      6.如果 obj 中的有对象是构造函数生成的,则结果中该对象的 constructor 将会丢失,变成 Object;
  • lodash 中的 cloneDeep 函数;
  • Jquery 中 $.extend([deep], target, object1 [, objectN]);
  • facebook 的 Immutable.js; Immutable.js了解一下?


  我们也可以通过 js 自己实现一个:

var deepCopy = function(obj) {
  // 不是对象不 Copy
  if (typeof obj !== 'object') return;
  // 根据obj的类型判断是新建一个数组还是对象
  var newObj = obj instanceof Array ? [] : {};

  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      // 判断属性是不是 object 以决定要不要递归
      newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
    }
  }
  return newObj;
}

 

 

  但是,上述深拷贝中仍然存在诸多问题:

  1. 性能上,深拷贝因为使用了递归,故必不如浅拷贝;
  2. 循环引用,如果对象的a属性和b属性互相有都挂载到自己的子属性上就会栈溢出;

 

posted @ 2019-07-25 09:55  shiweiqianju  阅读(268)  评论(0编辑  收藏  举报