[js基础]深拷贝的方法

js深拷贝,面试必问的,八说了,直接上菜~

使用递归方式进行深拷贝

let deepClone = (initalObj) => {
    const obj = {};
    if(typeof initalObj !== 'object'){
      return initalObj
    }
    for (const key in initalObj) {
      if (typeof initalObj[key] === 'object') {
        //对数组特殊处理
        if (Array.isArray(initalObj[key])) {
          //用map方法返回新数组,将数组中的元素递归
          obj[key] = initalObj[key].map(item => this.deepClone(item))
        } else {
          //递归返回新的对象
          obj[key] = this.deepClone(initalObj[key]);
        }
      } else if (typeof initalObj[key] === 'function') {
        //返回新函数
        obj[key] = initalObj[key].bind(obj);
      } else {
        //基本类型直接返回
        obj[key] = initalObj[key];
      }
    }
    return obj;
  }

const obj = {
  a1,
  b: {},
  c: { d: {}, g() => {} },
  e() =>{},
  ffunction ({}
}
const newObj = deepClone(obj);
newObj.a === obj.a  //true
newObj.b === obj.b  //false
newObj.c === obj .false  //false
newObj.c.d === obj.c.d  //false
newObj.c.g === obj.c.g  //false
newObj.e === obj.e  //false
newObj.f === obj.f  //false
  • 递归运行效率低,次数过多的话容易造成栈溢出。
  • 比较常用!兼容性好!

通过JSON序列化实现深拷贝

序列化后再反序列化。

 
function Clone(obj{
    var Copyobj = JSON.stringify(obj),
      //json字符串转json对象
      objClone = JSON.parse(Copyobj);
    return objClone;
 }

注意,这种方法容易出很多问题,实际并不常用!

  • 如果obj里有RegExp、Error对象,则序列化的结果将只得到空对象

  • 如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式。而不是时间对象

  • 如果obj里有函数,undefined,则序列化的结果会把函数或 undefined丢失

  • 如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null

  • 无法处理function,无法处理循环引用对象

lodash函数库实现深拷贝

var abj={
  a:1,
  b:2
}
var copyobj = lodash.cloneDeep(abj)

这个没啥好说的,就是调用库函数罢了,原理和第一个一样。

使用jq(extend)方法实现深拷贝

var obj= {
  a:10,
  b:function (){
    console.log(this.a)
  }
};
var newObj = $.extend(true,{},obj);

这个也没啥好说的,就是调用库函数…啊这

其他补充

slice()和concat()

使用slice、concat方法并不是真正的深拷贝!

它们只会复制第一层,而到了第二层及其之后,只会复制引用地址了!

使用方法如下:

  • 对于数组类型,可以使用slice(start, end)方法,返回一个新的数组。var arr1 = arr.slice(0);
  • 数组类型还可以使用concat()方法,var arr1 = arr.concat();

object.assign()

var obj1 = { a0 , b: { c0}};
var obj2 = Object.assign({}, obj1);

当对象中只有一级属性,没有二级属性的时候,此方法为深拷贝

如果是有多层嵌套呢?

 var obj1 = {
    a1,
    b2,
    c: ['a','b','c']
}
var obj2 = Object.assign({}, obj1);
obj2.c[1] = 5;
console.log(obj1.c); // ["a", 5, "c"]
console.log(obj2.c); // ["a", 5, "c"]

可以看到对于一层对象来说是没有任何问题的,但是如果对象的属性对应的是其它的引用类型的话,还是只拷贝了引用,修改的话还是会有问题。

所以可知,对象中有对象的时候,此方法在二级属性以后就是浅拷贝。

总结

从原理上来说,只有以下两种方法是无论有多少层嵌套都能实现真正的深拷贝。

  • 自定义递归方法
  • json序列化

但是json序列化容易出bug,所以实际编写工具函数时,都会用第一种方法。


原文始发于微信公众号(豆子前端):[js基础]深拷贝的方法

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/56736.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!