文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

js深拷贝和浅拷贝的深入讲解

2024-04-02 19:55

关注

浅拷贝

创建一个新的对象,来接受你要重新复制或引用的对象值。如果对象属性是基本的数据类型,复制的就是基本类型的值给新对象;但如果属性是引用数据类型,复制的就是内存中的地址,如果其中一个对象改变了这个内存中的地址,会影响到另一个对象。

实现方法

方法一:Object.assign

es6 中 object 的一个方法,用于 JS 对象的合并等,返回目标对象。它不会拷贝对象的继承属性和不可枚举的属性

let target = {};
let source = {a:{b:1}};
Object.assign(target,source)
console.log(taget) // {a:{b:1}}
target.a.b = 2;
console.log(taget) // {a:{b:2}}
console.log(source) // {a:{b:2}}

方法二:扩展运算符方式


let obj = {a:1,b:{c:1}}
let obj2 = {...obj}
obj.a = 2
console.log(obj)  //{a:2,b:{c:1}}
console.log(obj2); //{a:1,b:{c:1}}
obj.b.c = 2
console.log(obj)  //{a:2,b:{c:2}} 
console.log(obj2); //{a:1,b:{c:2}}

let arr = [1, 2, 3];
let newArr = [...arr]; 

方法三:concat和slice 浅拷贝数组

仅仅针对数组类型,都会返回一个新的数组对象。

concat 浅拷贝数组
let arr = [1, 2, 3];
let newArr = arr.concat();
newArr[1] = 100;
console.log(arr);  // [ 1, 2, 3 ]
console.log(newArr); // [ 1, 100, 3 ]

slice 浅拷贝数组
let arr = [1, 2, {val: 4}];
let newArr = arr.slice();
newArr[2].val = 1000;
console.log(arr);  //[ 1, 2, { val: 1000 } ]

深拷贝

将一个对象从内存中完整地拷贝出来一份给目标对象,并从堆内存中开辟一个全新的空间存放新对象,且新对象的修改并不会改变原对象,二者实现真正的分离。

实现方法

方法一:乞丐版(JSON.stringify和JSON.parse)

let obj1 = { a:1, b:[1,2,3] }
let str = JSON.stringify(obj1);
let obj2 = JSON.parse(str);
console.log(obj2);   //{a:1,b:[1,2,3]} 
obj1.a = 2;
obj1.b.push(4);
console.log(obj1);   //{a:2,b:[1,2,3,4]}
console.log(obj2);   //{a:1,b:[1,2,3]}

缺陷:

手写递归实现

基础版

 let obj = {a:{b:1}};
 function deepClone(obj){
  let cloneObj = Object.prototype.toString.call(obj) === "[object Array]" ? [] : {};
   for(let key in obj){
     if(typeof obj[key]=== "object" && obj !== null){
       cloneObj[key] = deepClone(obj[key])
     }else{
       cloneObj[key] = obj[key]
     }
   }
   return cloneObj;
 }
 let obj2 = deepClone(obj);
 obj2.a.b = 33
 console.log("obj",obj) // {a:{b:1}}
 console.log("obj2",obj2) // {a:{b:33}}

缺陷:  

改进版

const isComplexDataType = obj => (typeof obj === 'object' || typeof obj === 'function') && (obj !== null)
const deepClone = function (obj, hash = new WeakMap()) {
  if (obj.constructor === Date) 
  return new Date(obj)       // 日期对象直接返回一个新的日期对象
  if (obj.constructor === RegExp)
  return new RegExp(obj)     //正则对象直接返回一个新的正则对象
  //如果循环引用了就用 weakMap 来解决
  if (hash.has(obj)) return hash.get(obj)
  let allDesc = Object.getOwnPropertyDescriptors(obj)
  //遍历传入参数所有键的特性
  let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc)
  //继承原型链
  hash.set(obj, cloneObj)
  for (let key of Reflect.ownKeys(obj)) { 
    cloneObj[key] = (isComplexDataType(obj[key]) && typeof obj[key] !== 'function') ? deepClone(obj[key], hash) : obj[key]
  }
  return cloneObj
}

手写深拷贝参考:

https://www.jb51.net/article/247540.htm

https://www.jb51.net/article/247544.htm

其他实现方法

lodash库的_.cloneDeep方法,jQuery.extend()方法

FAQ:赋值和深浅拷贝的区别

注意:前提都是针对引用类型

赋值

当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。

let a = {name:'jimmy',b:{age:12}}
let b = a;
b.name = 'chimmy';
b.b.age = 21;
console.log(a) //  {name:'chimmy',b:{age:21}}
console.log(b) //  {name:'chimmy',b:{age:21}}

浅拷贝

重新在堆中创建内存,拷贝前后对象的基本数据类型互不影响,但拷贝前后对象的引用类型因共享同一块内存,会相互影响。

let a = {name:'jimmy',b:{age:12}}
let b = {...a};
b.name = 'chimmy';
b.b.age = 21;
console.log(a) //  {name:'jimmy',b:{age:21}}
console.log(b) //  {name:'chimmy',b:{age:21}}

深拷贝

将一个对象从内存中完整地拷贝出来一份给目标对象,并从堆内存中开辟一个全新的空间存放新对象,且新对象的修改并不会改变原对象,二者实现真正的分离。

let a = {name:'jimmy',b:{age:12}}
let b = {...a};
b.name = 'chimmy';
b.b.age = 21;
console.log(a) //  {name:'jimmy',b:{age:12}}
console.log(b) //  {name:'chimmy',b:{age:21}}

总结

到此这篇关于js深拷贝和浅拷贝的文章就介绍到这了,更多相关js深拷贝和浅拷贝内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯