范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

js中的浅拷贝和深拷贝

  js的数据类型: 基本数据类型:String、Number、Boolean、Null、Undefined; 引用数据类型:Object(Array、Date、Function、RegExp)。
  基本数据类型和引用数据类型的区别: 基本数据类型:存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配,是直接按值存放的,所以可以直接访问。 引用数据类型:引用类型(object)是存放在堆内存中的,变量实际上是一个存放在栈内存的指针,这个指针指向堆内存中的地址。每个空间大小不一样,要根据情况来进行特定的分配。 引用数据类型保存在堆内存中,然后在栈内存中保存了一个对堆内存中实际对象的引用,即数据在堆内存中的地址,JS对引用数据类型的操作都是操作对象的引用而不是实际的对象,如果obj1拷贝了obj2,那么这两个引用数据类型就指向了同一个堆内存对象,具体操作是obj1将栈内存的引用地址复制了一份给obj2,因而它们共同指向了一个堆内存对象;
  例如: var a = 1; b = a; // 栈内存会开辟一个新的内存空间,此时b和a都是相互独立的 b = 2; console.log(a); // 1
  例如: var arr = [1, 2, 3, 4]; arr1 = arr; //arr将栈内存的引用地址复制了一份给arr1,因而它们共同指向了一个堆内存对象; arr1[2] = 9; console.log(arr); //[1,2,9,4]
  基本数据类型值不可变: javascript中的原始值(undefined、null、布尔值、数字和字符串)与对象(包括数组和函数)有着根本区别。 原始值是不可更改的:任何方法都无法更改(或"突变")一个原始值。 对数字和布尔值来说显然如此 —— 改变数字的值本身就说不通,而对字符串来说就不那么明显了,因为字符串看起来像由字符组成的数组,我们期望可以通过指定索引来假改字符串中的字符。 实际上,javascript 是禁止这样做的。字符串中所有的方法看上去返回了一个修改后的字符串,实际上返回的是一个新的字符串值。
  基本数据类型的值是不可变的,动态修改了基本数据类型的值,它的原始值也是不会改变的, var str = "abc"; str[1] = "f"; console.log(str); //abc
  有很多操作字符串的方法,但是这些方法都是返回一个新的字符串,并没有改变其原有的数据。
  引用类型值可变 var a = [1, 2, 3]; a[1] = 5; console.log(a[1]); // 5
  浅拷贝 与 深拷贝: 浅拷贝和深拷贝都只针对于引用数据类型,浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存;但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象;浅拷贝只复制对象的第一层属性、深拷贝可以对对象的属性进行递归复制。
  区分深拷贝与浅拷贝,就是假设B复制了A,当修改B时,看A是否会发生变化,如果A也跟着变了,说明这是浅拷贝,拿人手短,如果A没变,那就是深拷贝,自食其力。
  浅拷贝:
  for···in只循环第一层 function simpleCopy(obj1) {     var obj2 = Array.isArray(obj1) ? [] : {};     for (let i in obj1) {         obj2[i] = obj1[i];     }     return obj2; } var obj1 = {     a: 1,     b: 2,     c: {         d: 3     } } var obj2 = simpleCopy(obj1); obj2.a = 3; obj2.c.d = 4; console.log(obj1.a); // 1 console.log(obj2.a); // 3 console.log(obj1.c.d); // 4 console.log(obj2.c.d); // 4
  Object.assign()实现浅拷贝及一层的深拷贝 var obj1 = {     a: {         b: 1     },     c: 2 } var obj2 = Object.assign({}, obj1) obj2.a.b = 3; obj2.c = 3 console.log(obj1.a.b); // 3 console.log(obj2.a.b); // 3 console.log(obj1.c); // 2 console.log(obj2.c); // 3
  Object实现拷贝2,浅拷贝 var obj1 = {     a: 1,     b: 2,     c: {         d: 3     } } var obj2 = Object.create(obj1); obj2.a = 3; obj2.c.d = 4; console.log(obj1.a); // 1 console.log(obj2.a); // 3 console.log(obj1.c.d); // 4 console.log(obj2.c.d); // 4
  深拷贝
  1、递归实现深拷贝 function deepCopy(obj1) {     var obj2 = Array.isArray(obj1) ? [] : {};     if (obj1 && typeof obj1 === "object") {         for (var i in obj1) {             var prop = obj1[i]; // 避免相互引用造成死循环,如obj1.a=obj             if (prop == obj1) {                 continue;             }             if (obj1.hasOwnProperty(i)) {                 // 如果子属性为引用数据类型,递归复制                 if (prop && typeof prop === "object") {                     obj2[i] = (prop.constructor === Array) ? [] : {};                     arguments.callee(prop, obj2[i]); // 递归调用                 } else {                     // 如果是基本数据类型,只是简单的复制                     obj2[i] = prop;                 }             }         }     }     return obj2; } var obj1 = {     a: 1,     b: 2,     c: {         d: 3     } } var obj2 = deepCopy(obj1); obj2.a = 3; obj2.c.d = 4; console.log(obj1.a); // 1 console.log(obj2.a); // 3 console.log(obj1.c.d); // 3 console.log(obj2.c.d); // 4
  2、Object.create实现深拷贝1,但也只能拷贝一层 function deepCopy(obj1) {     var obj2 = Array.isArray(obj1) ? [] : {};     if (obj1 && typeof obj1 === "object") {         for (var i in obj1) {             var prop = obj1[i]; // 避免相互引用造成死循环,如obj1.a=obj             if (prop == obj1) {                 continue;             }             if (obj1.hasOwnProperty(i)) {                 // 如果子属性为引用数据类型,递归复制                 if (prop && typeof prop === "object") {                     obj2[i] = (prop.constructor === Array) ? [] : Object.create(prop);                 } else {                     // 如果是基本数据类型,只是简单的复制                     obj2[i] = prop;                 }             }         }     }     return obj2; } var obj1 = {     a: 1,     b: 2,     c: {         d: 3     } } var obj2 = deepCopy(obj1); obj2.a = 3; obj2.c.d = 4; console.log(obj1.a); // 1 console.log(obj2.a); // 3 console.log(obj1.c.d); // 3 console.log(obj2.c.d); // 4
  3、使用JSON.stringify和JSON.parse实现深拷贝 JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象。 缺点: (1)如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式,而不是时间对象; (2)如果obj里有RegExp、Error对象,则序列化的结果将只得到空对象; (3)如果obj里有函数,undefined,则序列化的结果会把函数或 undefined丢失; (4)如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null; (5)JSON.stringify()只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor; (6)如果对象中存在循环引用的情况也无法正确实现深拷贝;
  以上,如果拷贝的对象不涉及上面讲的情况,可以使用JSON.parse(JSON.stringify(obj))实现深拷贝,但是涉及到上面的情况(除循环引用的情况外),可以考虑使用如下方法实现深拷贝。 function deepClone(data) {     const type = this.judgeType(data);     let obj;     if (type === "array") {         obj = [];     } else if (type === "object") {         obj = {};     } else {         // 不再具有下一层次         return data;     }     if (type === "array") {         // eslint-disable-next-line         for (let i = 0, len = data.length; i < len; i++) {             obj.push(this.deepClone(data[i]));         }     } else if (type === "object") {         // 对原型上的方法也拷贝了....         // eslint-disable-next-line         for (const key in data) {             obj[key] = this.deepClone(data[key]);         }     }     return obj; }   function judgeType(obj) {     // tostring会返回对应不同的标签的构造函数     const toString = Object.prototype.toString;     const map = {         "[object Boolean]": "boolean",         "[object Number]": "number",         "[object String]": "string",         "[object Function]": "function",         "[object Array]": "array",         "[object Date]": "date",         "[object RegExp]": "regExp",         "[object Undefined]": "undefined",         "[object Null]": "null",         "[object Object]": "object",     };     if (obj instanceof Element) {         return "element";     }     return map[toString.call(obj)]; }
  4、如果被拷贝中没有对时间、正则要求兼容,可以采用如下方法 function deepClone(obj){     let objClone = Array.isArray(obj)?[]:{};     if(obj && typeof obj==="object"){         for(key in obj){             if(obj.hasOwnProperty(key)){                 //判断ojb子元素是否为对象,如果是,递归复制                 if(obj[key]&&typeof obj[key] ==="object"){                     objClone[key] = deepClone(obj[key]);                 }else{                     //如果不是,简单复制                     objClone[key] = obj[key];                 }             }         }     }     return objClone; }
  5、热门的函数库lodash,也有提供_.cloneDeep用来做深拷贝
  6、jquery实现深拷贝,jquery 提供一个$.extend可以用来做深拷贝 var $ = require("jquery"); var obj1 = {     a: 1,     b: {         f: {         g: 1         }     },     c: [1, 2, 3] }; var obj2 = $.extend(true, {}, obj1); console.log(obj1.b.f === obj2.b.f);  // false

过渡期将结束,这6类电动车别买,喜欢网购的注意了随着过渡期即将结束,相关部门将对于超标电动车展开严查,超标电动车在过渡期结束将无法正常上路行驶,若是被交警查到也会受到处罚。不仅如此,很多地区已经对无牌电动车展开了管理,就算是电动加油时,为啥有些老司机更喜欢加200?对于这个问题,相信大家都有疑问,新车司机去加油时,往往选择一次性加满,而老司机在加油时会选择只加200元的,那么大家都没有想过为何会出现这个问题?这一选择与车主自身和对汽车的了解程美军撤离不忘洗白,美军行为和当年日本一样,堪称侵略军标配最近一周来,美国在阿富汗可谓是丢尽了面子花了二十年扶持的政权被塔利班用不到二十天的事件推翻不说,在喀布尔机场更是丑态百出。为了保证美国人可以率先撤走,驻守喀布尔机场的美军士兵甚至向对不起,我想说长津湖的存在就是意义公众号诺好杂谈关注了解人生百态今年的国庆被一部长津湖燃爆了。导演和演员通过自己的努力把那场无比艰辛与残酷的战役搬上了荧幕。长津湖是以1950年,中国志愿军部队与美军在长津湖地区交战网红直播喝农药,四男子跳河勇救人这一刻,我看到了人性的参差公众号诺好杂谈关注了解人生百态01hr这两天,一则新闻上了微博的热搜女网红患抑郁症,直播喝农药离开人世。在了解事情的来龙去脉后,我感到心情很沉重。罗小猫猫子是一名网红,拥有50万粉从众人追捧到谈之色变,媛究竟经历了怎样的污化公众号诺好杂谈关注了解人生百态近日杭州一幼儿园门口,一女子穿着黑色短裙,打着伞背着书包在门口摆拍。从路人视频中可以看到该女子妆容精致,穿着性感,那刻意摆弄的头发像极了刚从家中出门接再见爱人大结局一个词说透婚姻的真相公众号诺好杂谈关注了解人生百态最近三个月,有一部综艺可谓赚足了我的眼泪。这就是国内首档离婚综艺再见爱人。这档节目不撒糖,不狗血,不作秀,嘉宾们在婚姻中经历的困局哀伤暴躁以及温暖,如字节跳动取消大小周后,居然这么多人渴望加班?公众号关注诺好杂谈了解人生百态字节跳动取消大小周后薪资普降,这个话题引发了4亿人讨论。(图片来源网络侵删)前段时间,人社部,最高法联合发布10个超时加班典型案例,为企业划红线,并明从风光无限到人人喊凉,天天向上的结局是因为主持人的离开吗?公众号诺好杂谈关注了解人生百态打开豆瓣时,发现了下面这条帖子,如果不是看到这个问题,估计不少人跟我一样,都记不起是什么时候看过天天向上了?时间倒推10年,你一定还记得湖南卫视有那么iPhone被曝存在安全隐患,你中招了吗iPhone被曝存在安全隐患苹果我的隐患很大,你忍一下!NSOGroup的Pegasus恶意软件,通过iMessage入侵iPhone,不需要点击链接,也可以窃取信息和邮件,甚至调谁主导下一次科技革命?美媒列出九大科研方向,分析中美谁占上风自二战结束以来,世界科技发展进入了快车道,计算机航天航空生物科技等高新科技发展日新月异。只不过自冷战结束后,有很多人认为,世界科技进步的速度又慢了下来。然而历史的洪流注定不会让人类
华为P50Pro开放100元定金预售,每天1008发售目前华为P50Pro京东商城已经开放100元定金预售,每天1008限量发售,6488元起(8GB256GB)。据悉,此次华为P50Pro共有海思麒麟90004G芯片与高通骁龙888近视夜跑想听歌怎么办?试试可怡骨传导蓝牙眼镜根据马里兰医疗中心大学去年的一项研究,在过去6年里,行人戴着耳机出车祸的数字增长了3倍。更严重的是,70的事故中,跑步者或者行人不治身亡。夜跑对近视眼太不友好了!大量出汗带着又很不一年一度的运通汽车嘉年华,火热开启,您准备好了吗第七届运通嘉年华即将火热开启,7月24日30日,老时间,新玩法加倍福利等你拿!快带着小伙伴,一起体验精彩车生活。时至今日,运通集团已经成功举办6届运通嘉年华,往届多彩的活动丰厚的福3A平台加持ROG魔霸5R解锁极致性能战力要论专业电竞品牌,ROG必定榜上有名。凭借强大的实力积累,ROG软硬兼施不断推陈出新,为玩家们带来顶级笔记本产品,而ROG魔霸5R便是今年实力性能本的代表之一。作为笔记本市场罕见的5位达达快送骑能异士组团出道追逐平凡人滚烫火辣的梦想人生披荆斩棘的哥哥自播出后,各大平台话题不断,备受观众的喜爱与关注,成为当下最热门的网络综艺之一。而金典作为节目独家冠名品牌,联合达达集团旗下本地即时零售平台京东到家本地即时配送平台达一拳超人难想象的场景,埼玉爆破还有龙卷组队打BOSS,谁扛得住?看过一拳超人动漫的朋友应该知道,在这部动漫中,每个英雄都有相应的评级,而根据原著中的实力排行,这其中总共出现了17位S级英雄。而这17位S级英雄中,公认最强的三位分别是爆破龙卷以及小家也能实现大屏自由,峰米R1搭载联发科MT9669硬件实力出众随着现代家居环境和人们观影习惯的改变,投影产品正成为众多家庭的共同选择。尤其是随放随用无投影距离限制的激光超短焦投影仪,成为现代家庭实现大屏自由的不二之选。火热的市场催生了大量优质永劫无间风靡全球华硕重炮手主板助你吃鸡永劫无间将在8月12日登陆SteamEpic平台开启全球公测,届时除了阴阳师联名的妖刀姬参战外,全新英雄也会一一亮相,另外全新武器匕首也将随着第一赛季一同推出。该作于去年开放测试后MPV教科书混动天花板,广汽丰田赛那能不能买?从去年五月份首发至今,新一代丰田SIENNA(中文名赛那)的相关信息就一直是媒体和车友关注的重点。10月30日,广汽丰田赛那SIENNA正式上市,这是丰田TNGA架构下的首款MPV惊悚回归死亡空间重制版公布制作随着近几年网络视频直播行业的发展,一些惊悚动作类游戏的热度逐渐攀升甚至出圈已屡见不鲜,尤其是一些经典的恐怖动作类游戏,如寂静岭逃生生化危机等,每一次推出精神续作都能收获忠实粉丝的大广汽蔚来焕新而来,助力自动驾驶新生态落地广州广汽蔚来焕新而来,助力自动驾驶新生态落地广州2021年中国汽车行业电动化转型加速,新能源汽车销量快速放大,今年第一季度国内汽车市场新能源汽车的销量为46。6万台。新能源车市场正逐渐