js实现深拷贝

展开运算符...和Object.assign都是浅拷贝,常见的js方法如slice也是浅拷贝,那如何实现深拷贝呢?

// 需要递归拷贝 
function deepClone(obj) {
  // 如果传递的是null 那就不处理
  // 函数没有引用关系
  if (typeof obj !== 'object') return obj;
  if (obj == null) return null;
  // 处理日期和正则
  if (obj instanceof RegExp) return new RegExp(obj);
  if (obj instanceof Date) return new Date(obj);
   // Object.prototype.toString.call(obj) === '[object Array]', 这么判断保留不了继承关系
  let instance = new obj.constructor(); // 看当前实例的constructor
  // 实现深拷贝
  //for...in循环是 遍历对象的每一个可枚举属性,包括原型链上面的可枚举属性,
   for (let key in obj) {
            if(obj.hasOwnProperty(obj[key])) {
                instance[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]
            }
        }
  return instance;
}
// 函数不需要重新拷贝
let obj = { a: { a: 1 } }
let newObj = deepClone(obj);
obj.a.a = 2;
console.log(newObj);

复制代码思路是首先判断obj类型,null、Date对象,数组、正则、以及对象的typeof结果都是oobject,
需要单独分情况考虑。
对于null、Date对象以及正则,我们直接返回数值就可以了
对于数组,我们没有直接返回,因为数组可能有继承关系,需要保留继承关系,这个需要注意。
1)判断数组类型我们没用Object.prototype.toString.call(obj),因为它保留不了继承关系。
举例如下:

var t = [1,2]
t.__proto__={a:1}
Object.prototype.toString.call(t) ----> // "[object Array]"
t.constructor ----->  // ƒ Object() { [native code] }
new t.constructor() --> objcet

总结

实现深拷贝的几个要点:

  1. 需要递归拷贝。
  2. 需要判断类型
  3. 无法拷贝proto
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一般不会深拷贝函数等,所以一般用递归和JSON方法即可。 如果要实现函数等拷贝,比较完美的做法: function...
    Gen_阅读 4,355评论 0 0
  • JS深拷贝 JS中拷贝对象可以按照拷贝的程度可以分为浅拷贝和深拷贝,有些时候我们需要拷贝之后的对象和拷贝之前的对象...
    大雄的学习人生阅读 6,723评论 0 12
  • JS中拷贝对象可以按照拷贝的程度可以分为浅拷贝和深拷贝,有些时候我们需要拷贝之后的对象和拷贝之前的对象解耦,即脱离...
    指尖跳动阅读 4,840评论 0 0
  • 什么是深拷贝,什么是浅拷贝 说到深浅拷贝,就不得不提到另外一个知识点,那就是引用类型和基本类型以及堆和栈的区别。再...
    jeff_nz阅读 4,408评论 0 0
  • 概要 64学时 3.5学分 章节安排 电子商务网站概况 HTML5+CSS3 JavaScript Node 电子...
    阿啊阿吖丁阅读 13,117评论 0 3