电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

詳細(xì)分析JavaScript中的深淺拷貝

瀏覽:72日期:2023-10-13 09:43:47

在說JS中深淺拷貝之前,我們需要對JS中的數(shù)據(jù)類型有所了解,分為基本數(shù)據(jù)類型與引用數(shù)據(jù)類型,對于基本數(shù)據(jù)類型并沒有深淺拷貝的說法,深淺拷貝主要針對引用數(shù)據(jù)類型。

一、淺拷貝

淺拷貝只復(fù)制了引用,并沒有復(fù)制值。在JS中最簡單的淺拷貝就是利用“=”賦值操作符來實(shí)現(xiàn)。

var obj1 = { a:1, b:[2,3,4], c:{name:’tanj’}, fun:function(){ console.log(’fun’) }}var obj2 = obj1obj2.a = 666 /* 修改obj2的值,obj1的值也隨之改變 */console.log(obj1) /* {a: 666, b: Array(3), c: {…}, fun: ƒ} */

上述代碼中,我們修改obj2的值,obj1的值也隨之發(fā)生了改變,使用”=“只實(shí)現(xiàn)了淺拷貝。

二、深拷貝

深拷貝是對目標(biāo)的完全拷貝,進(jìn)行深拷貝后的兩個(gè)值互不影響。

1. 利用JSON.stringify與JSON.parse方法

JSON.stringify將一個(gè)JavaScript值轉(zhuǎn)換為JSON字符串;

JSON.parse將一個(gè)JSON字符串轉(zhuǎn)換為JavaScript值。

var obj1 = { a:1, b:[2,3,4], c:{name:’tanj’},}var obj2 = JSON.parse(JSON.stringify(obj1))obj2.a = 12console.log(obj1) /* {a: 1, b: Array(3), c: {…}} */

修改obj2的值并沒有影響到obj1中的屬性值,顯然,我們利用JSON.parse與JSON.stringify實(shí)現(xiàn)了深拷貝。

但是,真的可以這么簡單的實(shí)現(xiàn)嗎?我們來看看下面的例子!

var obj1 = { a:1, b:[2,3,4], c:{name:’tanj’}, fun:function(){ console.log(’fun’) }}var obj2 = JSON.parse(JSON.stringify(obj1))obj2.a = 12console.log(obj1) /* {a: 1, b: Array(3), c: {…}, fun: ƒ} */console.log(obj2) /* {a: 12, b: Array(3), c: {…}} */

轉(zhuǎn)換后的obj2中沒有了fun這個(gè)屬性,這是由于在利用JSON.stringify轉(zhuǎn)換過程中,忽略了undefined、function、symbol。顯然,當(dāng)我們的對象中出現(xiàn)這些類型的屬性時(shí)無法利用該方法實(shí)現(xiàn)深拷貝。

2. 遞歸

function deepClone(source){ if(!isObject(source)) return source var newObj = source instanceof Array? []:{} for(let key in source){if(source.hasOwnProperty(key)){ newObj[key] = isObject(source[key])?deepClone(source[key]):source[key] } } return newObj}function isObject(x) { return typeof x === ’object’ && x != null}

測試一下上述方法:

var obj1 = { a:1, b:[2,3,4], c:{name:’tanj’}, fun:function(){console.log(’fun’) }}var obj2 = deepClone(obj1)obj2.a = 12console.log(obj1) /* {a: 1, b: Array(3), c: {…}, fun: ƒ} */

通過例子可以看到,我們修改了obj2中a屬性的值,但是并沒有影響到obj1中的a屬性值。通過遞歸我們可以實(shí)現(xiàn)深拷貝!

注意:上述方法未解決循環(huán)引用的問題。

var obj1 = {}obj1.a = obj1var obj2 = deepClone(obj1) /* 報(bào)錯(cuò),棧溢出 */console.log(obj2)

關(guān)于如何解決循環(huán)引用問題以及實(shí)現(xiàn)Symbol類型拷貝,稍后完善。

三、其他拷貝方法

1. 數(shù)組中的concat()和slice()方法

我們知道數(shù)組中有兩個(gè)方法concat和slice可以完成復(fù)制數(shù)組,并且返回新數(shù)組。以concat為例。

var arr = [1,2,3]var arr2 = arr.concat()arr2[2]=4console.log(arr) /* [1, 2, 3] */console.log(arr2) /* [1, 2, 4] */

改變arr2的值,并沒有影響到arr的值,這是實(shí)現(xiàn)了數(shù)組的深拷貝嗎,先不急于下結(jié)論,一起看看下面的例子再來分析:

var arr = [1,2,3,[4,5,6],{a:7}]var arr2 = arr.concat()arr2[3] = 444arr2[4].a=8console.log(arr) /* [1,2,3,[4,5,6],{a:8}] */console.log(arr2) /* [1,2,3,444,{a:8}] */

我們直接修改arr2[3],并沒有引起arr的改變,但是我們修改arr2[4].a時(shí),arr中的相應(yīng)元素跟著一起發(fā)生了改變。其實(shí),我們對arr2數(shù)組中的元素直接進(jìn)行改變(比如:arr2[0]=***,arr2[1]=***,arr2[3]=***)時(shí),不會(huì)影響到原數(shù)組arr,但是我們修改數(shù)組中的[3,4,5]或{a:7}時(shí),會(huì)造成原數(shù)組arr的改變。

結(jié)論:concat()方法對數(shù)組第一層進(jìn)行了深拷貝。

可以再試試數(shù)組的slice()方法,它也是只對數(shù)組第一層進(jìn)行了深拷貝。

2. Object.assign()和...展開運(yùn)算符

var obj1 = { a:1, b:[2,3,4], c:{name:’tanj’}}var obj2 = {...obj1}obj2.a = 666obj2.c.name = ’xinxin’console.log(obj1) /* {a:1,b:[2,3,4],c:{name:’xinxin’}} */

可以看到利用...展開運(yùn)算符實(shí)現(xiàn)的是對象第一層的深拷貝。后面的只是拷貝的引用值。

可以試試Object.assign()方法:

var obj1 = { a:1, b:[2,3,4], c:{name:’tanj’}}var obj2 = {}Object.assign(obj2,obj1)obj2.a = 666obj2.b[0] = 0console.log(obj1) /* {a:1,b:[0,3,4],c:{name:’tanj’} */

同樣,只對對象第一層進(jìn)行了深拷貝,假如源對象的屬性值(例如obj1)是一個(gè)指向?qū)ο蟮囊茫琽bj2也只拷貝那個(gè)引用值。所以改變obj2中b所指向的那個(gè)數(shù)組時(shí),obj1的值也會(huì)發(fā)生改變。

我們可以自己實(shí)現(xiàn)一個(gè)這樣的效果,只對第一層進(jìn)行深拷貝:

function shallowClone(source) { const newObj = source.constructor === Array ? [] : {} for (let keys in source) { if (source.hasOwnProperty(keys)) { newObj[keys] = source[keys]} } return newObj}

以上就是分析JavaScript中的深淺拷貝的詳細(xì)內(nèi)容,更多關(guān)于JavaScript 深淺拷貝的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: JavaScript
相關(guān)文章:
主站蜘蛛池模板: 深圳宣传片制作_产品视频制作_深圳3D动画制作公司_深圳短视频拍摄-深圳市西典映画传媒有限公司 | 精准猎取科技资讯,高效阅读科技新闻_科技猎 | 齿轮减速电机一体机_蜗轮蜗杆减速马达-德国BOSERL齿轮减速机带电机生产厂家 | 仓储货架_南京货架_钢制托盘_仓储笼_隔离网_环球零件盒_诺力液压车_货架-南京一品仓储设备制造公司 | 滚筒烘干机_转筒烘干机_滚筒干燥机_转筒干燥机_回转烘干机_回转干燥机-设备生产厂家 | 活性炭-果壳木质煤质柱状粉状蜂窝活性炭厂家价格多少钱 | 优考试_免费在线考试系统_培训考试系统_题库系统_组卷答题系统_匡优考试 | 微水泥_硅藻泥_艺术涂料_艺术漆_艺术漆加盟-青岛泥之韵环保壁材 武汉EPS线条_EPS装饰线条_EPS构件_湖北博欧EPS线条厂家 | 真空泵维修保养,普发,阿尔卡特,荏原,卡西亚玛,莱宝,爱德华干式螺杆真空泵维修-东莞比其尔真空机电设备有限公司 | 至顶网| 聚氨酯催化剂K15,延迟催化剂SA-1,叔胺延迟催化剂,DBU,二甲基哌嗪,催化剂TMR-2,-聚氨酯催化剂生产厂家 | 电线电缆厂家|沈阳电缆厂|电线厂|沈阳英联塑力线缆有限公司 | 土壤有机碳消解器-石油|表层油类分析采水器-青岛溯源环保设备有限公司 | 江苏南京多语种翻译-专业翻译公司报价-正规商务翻译机构-南京华彦翻译服务有限公司 | 外贮压-柜式-悬挂式-七氟丙烷-灭火器-灭火系统-药剂-价格-厂家-IG541-混合气体-贮压-非贮压-超细干粉-自动-灭火装置-气体灭火设备-探火管灭火厂家-东莞汇建消防科技有限公司 | 心肺复苏模拟人|医学模型|急救护理模型|医学教学模型上海康人医学仪器设备有限公司 | 广东恩亿梯电源有限公司【官网】_UPS不间断电源|EPS应急电源|模块化机房|电动汽车充电桩_UPS电源厂家(恩亿梯UPS电源,UPS不间断电源,不间断电源UPS) | 砂石生产线_石料生产线设备_制砂生产线设备价格_生产厂家-河南中誉鼎力智能装备有限公司 | 厦门ISO认证|厦门ISO9001认证|厦门ISO14001认证|厦门ISO45001认证-艾索咨询专注ISO认证行业 | 重庆网站建设,重庆网站设计,重庆网站制作,重庆seo,重庆做网站,重庆seo,重庆公众号运营,重庆小程序开发 | 齿式联轴器-弹性联轴器-联轴器厂家-江苏诺兴传动联轴器制造有限公司 | 金属雕花板_厂家直销_价格低-山东慧诚建筑材料有限公司 | 99文库_实习生实用的范文资料文库站 | 搅拌磨|搅拌球磨机|循环磨|循环球磨机-无锡市少宏粉体科技有限公司 | 粤丰硕水性环氧地坪漆-防静电自流平厂家-环保地坪涂料代理 | 高精度电阻回路测试仪-回路直流电阻测试仪-武汉特高压电力科技有限公司 | 行星搅拌机,双行星搅拌机,动力混合机,无锡米克斯行星搅拌机生产厂家 | 天然鹅卵石滤料厂家-锰砂滤料-石英砂滤料-巩义东枫净水 | 不锈钢轴流风机,不锈钢电机-许昌光维防爆电机有限公司(原许昌光维特种电机技术有限公司) | CCE素质教育博览会 | CCE素博会 | 教育展 | 美育展 | 科教展 | 素质教育展 | 日本细胞免疫疗法_肿瘤免疫治疗_NK细胞疗法 - 免疫密码 | 1000帧高速摄像机|工业高速相机厂家|科天健光电技术 | 安徽净化板_合肥岩棉板厂家_玻镁板厂家_安徽科艺美洁净科技有限公司 | 化工ERP软件_化工新材料ERP系统_化工新材料MES软件_MES系统-广东顺景软件科技有限公司 | 同步带轮_同步带_同步轮_iHF合发齿轮厂家-深圳市合发齿轮机械有限公司 | 陕西安玻璃自动感应门-自动重叠门-磁悬浮平开门厂家【捷申达门业】 | 定量包装机,颗粒定量包装机,粉剂定量包装机,背封颗粒包装机,定量灌装机-上海铸衡电子科技有限公司 | 泉州陶瓷pc砖_园林景观砖厂家_石英砖地铺石价格 _福建暴风石英砖 | 螺杆式冷水机-低温冷水机厂家-冷冻机-风冷式-水冷式冷水机-上海祝松机械有限公司 | 桨叶搅拌机_螺旋挤压/方盒旋切造粒机厂家-无锡市鸿诚输送机械有限公司 | 柴油机_柴油发电机_厂家_品牌-江苏卡得城仕发动机有限公司 |