大家好,我是IT修真院成都分院的學(xué)員禀苦,一枚正直純潔善良的WEB前端程序員蔓肯。
今天給大家分享一下,修真院官網(wǎng)JS任務(wù)4如何實(shí)現(xiàn)數(shù)組深拷貝和淺拷貝振乏?
1.背景介紹
在JavaScript中蔗包,數(shù)據(jù)類型有以下幾種:?
基本類型:Number Boolean String undefined null?
引用類型:Object Function 基本類型的數(shù)據(jù)是存放在棧內(nèi)存中的,而引用類型的數(shù)據(jù)是存放在堆內(nèi)存中的?
基本類型的復(fù)制就是在棧內(nèi)存中開辟出了一個(gè)新的存儲(chǔ)區(qū)域用來存儲(chǔ)新的變量慧邮,這個(gè)變量有它自己的值调限,只不過和前面的值一樣,所以如果其中一個(gè)的值改變误澳,則不會(huì)影響到另一個(gè)耻矮。?
對(duì)于引用類型,定義了一個(gè)對(duì)象其實(shí)是在棧內(nèi)存中存儲(chǔ)了一個(gè)指針忆谓,這個(gè)指針指向堆內(nèi)存中該對(duì)象的存儲(chǔ)地址裆装。復(fù)制給另一個(gè)對(duì)象的過程其實(shí)是把該對(duì)象的地址復(fù)制給了另一個(gè)對(duì)象變量,兩個(gè)指針都指向同一個(gè)對(duì)象,所以若其中一個(gè)修改了哨免,則另一個(gè)也會(huì)改變茎活。?
2.知識(shí)剖析
這種拷貝分為兩種情況:拷貝引用和拷貝實(shí)例,也就是淺拷貝和深拷貝 琢唾。
JavaScript存儲(chǔ)對(duì)象都是存地址的载荔,所以淺拷貝會(huì)導(dǎo)致 obj1 和obj2 指向同一塊內(nèi)存地址。改變了其中一方的內(nèi)容采桃,都是在原來的內(nèi)存上做修改會(huì)導(dǎo)致拷貝對(duì)象和源對(duì)象都發(fā)生改變懒熙,而深拷貝是開辟一塊新的內(nèi)存地址,將原對(duì)象的各個(gè)屬性逐個(gè)復(fù)制進(jìn)去普办。對(duì)拷貝對(duì)象和源對(duì)象各自的操作互不影響工扎。
3.常見問題
4.解決方案
JS數(shù)組的淺拷貝:
簡(jiǎn)單的賦值就是淺拷貝。因?yàn)閷?duì)象和數(shù)組在賦值的時(shí)候都是引用傳遞泌豆。賦值的時(shí)候只是傳遞一個(gè)指針。
淺拷貝很容易吏饿,但是很多時(shí)候我們需要原樣的把數(shù)組或者對(duì)象復(fù)制一份踪危,在修改值的時(shí)候,不改變初始對(duì)象的值猪落。這個(gè)時(shí)候就需要使用深拷貝贞远。
JS數(shù)組的深拷貝:
方法一:JS的SLICE函數(shù):
slice() 方法可從已有的數(shù)組中返回選定的元素。?
【語法】arrayObject.slice(start,end)?
【參數(shù)】arrayObj--必選項(xiàng):一個(gè)Array對(duì)象笨忌。start--必選項(xiàng):arrayObj中所指定的部分的開始元素是從零開始計(jì)算的下標(biāo)蓝仲。end--可選項(xiàng):arrayObj中所指定的部分的結(jié)束元素是從零開始計(jì)算的下標(biāo)。?
【說明】 slice 方法返回一個(gè)Array對(duì)象官疲,其中包含了arrayObj的指定部分袱结。slice方法一直復(fù)制到end所指定的元素(不包括該元素)。 如果start為負(fù)途凫,將它作為length + start處理垢夹,此處length為數(shù)組的長(zhǎng)度。如果end為負(fù)维费,就將它作為length + end處理果元,此處length為數(shù)組的長(zhǎng)度。如果省略end 犀盟,那么slice方法將一直復(fù)制到 arrayObj 的結(jié)尾而晒。如果end出現(xiàn)在start之前,不復(fù)制任何元素到新數(shù)組中阅畴。
方法二:JS的CONCAT函數(shù)
concat() 方法用于連接兩個(gè)或多個(gè)數(shù)組倡怎。該方法不會(huì)改變現(xiàn)有的數(shù)組,而僅僅會(huì)返回被連接數(shù)組的一個(gè)副本。 【語法】arrayObject.concat(arrayX,arrayX,......,arrayX)?
【參數(shù)】arrayX--必需:該參數(shù)可以是具體的值诈胜,也可以是數(shù)組對(duì)象豹障。可以是任意多個(gè)焦匈。?
【說明】 返回一個(gè)新的數(shù)組血公。該數(shù)組是通過把所有 arrayX 參數(shù)添加到 arrayObject 中生成的。如果要進(jìn)行 concat()操作的參數(shù)是數(shù)組缓熟,那么添加的是數(shù)組中的元素累魔,而不是數(shù)組。
除了上述兩個(gè)方法外够滑,還有沒有其他的深拷貝方法?
js遍歷數(shù)組的方法:
利用JSON格式:
這種方法使用較為簡(jiǎn)單彰触,可以滿足基本的深拷貝需求况毅,而且能夠處理JSON格式能表示的所有數(shù)據(jù)類型尔许,但是對(duì)于正則表達(dá)式類型蒸甜、函數(shù)類型等無法進(jìn)行深拷貝(而且會(huì)直接丟失相應(yīng)的值)柠新。
slice()登颓、concat()的局限性在哪里?
由上面的例子可以看出痢甘,slice和concat這兩個(gè)方法塞栅,僅適用于對(duì)不包含引用對(duì)象的一維數(shù)組的深拷貝。
5..更多討論
答:jQuery中的$.extend淺拷貝愉粤,拷貝對(duì)象A時(shí)拿撩,對(duì)象B將拷貝A的所有字段压恒,如果字段是內(nèi)存地址型宙,B將拷貝地址妆兑,若果字段是基元類型,B將復(fù)制其值谱姓。它的缺點(diǎn)是如果你改變了對(duì)象B所指向的內(nèi)存地址,你同時(shí)也改變了對(duì)象A指向這個(gè)地址的字段狈癞。 jQuery中的$.extend深拷貝,這種方式會(huì)完全拷貝所有數(shù)據(jù)茂契,優(yōu)點(diǎn)是B與A不會(huì)相互依賴(A,B完全脫離關(guān)聯(lián)), 缺點(diǎn)是拷貝的速度更慢掉冶,代價(jià)更大。
http://bijian1013.iteye.com/blog/2255037
答:引用類型璧亚,定義了一個(gè)對(duì)象其實(shí)是在棧內(nèi)存中存儲(chǔ)了一個(gè)指針讨韭,這個(gè)指針指向堆內(nèi)存中該對(duì)象的存儲(chǔ)地址狰闪。復(fù)制給另一個(gè)對(duì)象的過程其實(shí)是把該對(duì)象的地址復(fù)制給了另一個(gè)對(duì)象變量,兩個(gè)指針都指向同一個(gè)對(duì)象濒生,所以若其中一個(gè)修改了埋泵,則另一個(gè)也會(huì)改變。?
鳴謝
感謝大家觀看
----
技能樹.IT修真院
“我們相信人人都可以成為一個(gè)工程師甜攀,現(xiàn)在開始秋泄,找個(gè)師兄,帶你入門规阀,掌控自己學(xué)習(xí)的節(jié)奏恒序,學(xué)習(xí)的路上不再迷茫”谁撼。
這里是技能樹.IT修真院歧胁,成千上萬的師兄在這里找到了自己的學(xué)習(xí)路線,學(xué)習(xí)透明化厉碟,成長(zhǎng)可見化喊巍,師兄1對(duì)1免費(fèi)指導(dǎo)」抗模快來與我一起學(xué)習(xí)吧?崭参!