文章详情

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

请输入下面的图形验证码

提交验证

短信预约提醒成功

怎么解决JavaScript的深浅拷贝

2023-06-27 11:09

关注

这篇文章主要讲解了“怎么解决JavaScript的深浅拷贝”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么解决JavaScript的深浅拷贝”吧!

正文

从一则故事讲起,昨天因为医院开不出药,我拿上药取小区药店去买药,进门之后我问老板有没有这个药,老板转身进去一个小屋子拿了一盒药,果不其然确实有,药的名字和毫克一摸一样,但是盒子的样子和厂商不一样,我问老板:“这两个药是一种药吗,盒子不一样啊,药的成分是一样的吗?”老板说当然一样啊,这个就和你去买猪肉一样,同样是猪身上的肉,只不过是你去这个超市和去其他超市买场地一样而已。最后为了安全起见,我还是没有买那个药。

"拷贝"分为浅拷贝和深拷贝。它是针对对象来说的,如果不是对象一切免谈。这里的对象可以理解为我拿的那盒药,浅拷贝可以理解为老板拿出来的那盒药,虽然药的名字和毫克一样,然后里面的我们不知道是否真的一样,可能一样可能不一样。深拷贝可以理解为我买到了一摸一样的药,一层一层的药名,毫克,厂商,成分都一样。

总结:

下面看一个浅拷贝的例子:

let school={'name':"W3Cschool"};let my = {age:{count:18},name:"W3Cschool编程网"};let all = {...school,...my};my.age.count=100;console.log(all);console.log(my);

结果:

{ age: { count: 100 }, name: 'W3Cschool编程网' }{ age: { count: 100 }, name: 'W3Cschool编程网' }

结论是:浅拷贝修改拷贝之后的对象上的属性会把原对象身上的属性同时修改掉。

下面再看一个深拷贝的例子:

const _ = require("loadsh")let my = {age:{count:18},name:"W3Cschool编程网"};let all = _.cloneDeep(my);all.age.count =100;console.log(my);console.log(all);

结果:

{ age: { count: 18 }, name: 'W3Cschool编程网' }{ age: { count: 100 }, name: 'W3Cschool编程网' }

结论是:深拷贝修改拷贝之后的对象上的属性不会把原对象身上的属性同时修改掉。

拷贝的方法

数组方法:slice和concat

let arr = [1,2,3,4];let arr2 = arr.slice(0)arr2[2]=5;console.log(arr);  //[ 1, 2, 3, 4 ]console.log(arr2); //[ 1, 2, 5, 4 ]

当数组里是不是对象的时候从结果上看是深拷贝,在看下面例子

let arr = [{1:1,2:2}];let arr2 = arr.slice(0)arr2[2]=5;console.log(arr);  //[ { '1': 1 }, { '2': 5 } ]console.log(arr2); //[ { '1': 1 }, { '2': 5 } ]

当数组里是对象的时候就变成了浅拷贝

let arr = [1,2,3,4];let arr2 = [].concat(arr);arr2[2]=5;console.log(arr); //[ 1, 2, 3, 4 ]  ✔console.log(arr2); //[ 1, 2, 5, 4 ]

当数组里不是对象的时候从结果上看是深拷贝,在看下面例子

let arr = [{1:1},{2:2}];let arr2 = arr.cancat(0)arr2[1][2]=5;console.log(arr);  //[ { '1': 1 }, { '2': 5 } ]  ❌变成了引用console.log(arr2); //[ { '1': 1 }, { '2': 5 } ]

当数组里是对象的时候就变成了浅拷贝

总结:只有当数组是一维数组而且不包含对象的时候才是深拷贝

(推荐教程:JavaScript教程)

Object.assgin()

let a= {a:1,b:2};let b= Object.assign({},a);a.a=3;console.log(a)  //{a: 3, b: 2}console.log(b)  //{a: 1, b: 2}  ✔let a= {a:1,b:{c:2}};let b= Object.assign({},a);a.b.c=3;console.log(a)  //{a: 1, b: {c:3}}console.log(b)  //{a: 1, b: {c:3}}   ❌变成了引用

总结:Object.assgin如果涉及到嵌套多个对象的话就变成了引用 解决方法:使用JSON.stringify()先转化成字符串,再通过JSON.parse()转化成对象

let a= {a:1,b:{c:2}};let b= JSON.parse(JSON.stringify(a))a.b.c=3;console.log(a)  //{a: 1, b: {c:3}}console.log(b)  //{a: 1, b: {c:2}}   ✔let school={'name':"W3Cschool编程网",fn:function(){}};let my = {age:{count:18},name:"W3Cschool编程网"};let all=JSON.parse(JSON.stringify({...school,...my}))console.log(all);  //{'name':"W3Cschool编程网",age:{count:18}}; //❌把fn给丢了

总结: JSON.parse(JSON.stringify()) 这个方法有一定的局限性,会丢失 fn 。

let deepClone=(obj)=>{    if(obj==undefined) return obj;  //undefined == null    if(obj instanceof RegExp) return new RegExp(obj);    if(obj instanceof Date) return new Date(obj);    if(typeof obj!=="object") return obj;    let newObj = new obj.constructor;    for(let key in obj){        if(obj.hasOwnProperty(key)){            newObj[key] = deepClone(obj[key])        }    }    return newObj;}let obj1 = {name:{age:"10"}}let n = deepClone(obj1)obj1.name.age = "231"console.log(n);  //{name:{age:"10"}}  ✔let obj = { name:"W3Cschool编程网" }obj.aaa=objlet n = deepClone(obj1)console.log(n);  //死循环了  ❌

解决这个问题可以使用WeakMap

let deepClone=(obj,hash=new WeakMap())=>{    if(obj==undefined) return obj;  //undefined == null    if(obj instanceof RegExp) return new RegExp(obj);    if(obj instanceof Date) return new Date(obj);    if(typeof obj!=="object") return obj;    if(hash.has(obj)) return hash.get(obj);    let newObj = new obj.constructor;    hash.set(obj,newObj);    for(let key in obj){        if(obj.hasOwnProperty(key)){            newObj[key] = deepClone(obj[key],hash)        }    }    return newObj;}
<br> 源码地址:https://github.com/lodash/lodash/blob/86a852fe763935bb64c12589df5391fd7d3bb14d/.internal/baseClone.js<br> ```
function clone (value) {  if (Array.isArray(value)) {    return value.map(clone)  } else if (value && typeof value === 'object') {    const res = {}    for (const key in value) {      res[key] = clone(value[key])    }    return res  } else {    return value  }}let arr = [{1:1},{2:2},function(){}];let arr2 = clone(arr)arr2[1][2]=5;console.log(arr)  //[ { '1': 1 }, { '2': 2 }, [Function (anonymous)] ]   ✔ 深拷贝console.log(arr2); //[ { '1': 1 }, { '2': 5 }, [Function (anonymous)] ]function extend (a, b) {  for (const key in b) {    a[key] = b[key]  }  return a}let b={a:1,b:{c:2}};let a= extend({},b);a.b.c=5;console.log(a);  //{ a: 1, b: { c: 5 } }console.log(b);  //{ a: 1, b: { c: 5 } }   浅拷贝

感谢各位的阅读,以上就是“怎么解决JavaScript的深浅拷贝”的内容了,经过本文的学习后,相信大家对怎么解决JavaScript的深浅拷贝这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

阅读原文内容投诉

免责声明:

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

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

软考中级精品资料免费领

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

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

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

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

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

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

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