摘要:拷貝分為淺拷貝和深拷貝。淺拷貝是引用復(fù)制,深拷貝是完全單純拷貝數(shù)據(jù)的值。所以,這種方法只是簡單繞過第一層箱子的引用復(fù)制深拷貝目前比較好的方法就是大法,要么就是自己寫遞歸的深拷貝函數(shù)。附帶深拷貝的自定義函數(shù)源自大佬的
經(jīng)常遇到數(shù)組或?qū)ο蟮纫妙愋妥鳛楹瘮?shù)的參數(shù)的情況,但又不想修改原來的數(shù)據(jù),這時(shí)候就需要拷貝(基本類型的變量不需要考慮)。
拷貝分為淺拷貝和深拷貝。淺拷貝是引用復(fù)制,深拷貝是完全單純拷貝數(shù)據(jù)的值。因?yàn)閿?shù)組是最常見的引用類型,所以下面大部分拿數(shù)組舉例。
淺拷貝
簡單把引用復(fù)制
var a = [1,2,3] var b = a console.log(b) //Array(3) [1, 2, 3] b[1] = 0 console.log(b) //Array(3) [1, 0, 3] console.log(a) //Array(3) [1, 0, 3]
可以看出,修改數(shù)組b的時(shí)候,數(shù)組a也被修改了。這顯然不是想要的做法。
要想不改變原來的數(shù)組,就要用到以下的幾種方法:
循環(huán) for(...)
concat方法
var a = [1,2,3] var b = a.concat() //或 var b = [].concat(a) console.log(b) //Array(3) [1, 2, 3] b[1] = 0 console.log(b) //Array(3) [1, 0, 3] console.log(a) //Array(3) [1, 2, 3]
slice方法
var a = [1,2,3,4,5] var b = a.slice(0) console.log(b) //Array(5) [1, 2, 3, 4, 5] b[0] = 0 console.log(a) //Array(5) [1, 2, 3, 4, 5] console.log(b) //Array(5) [0, 2, 3, 4, 5]
還可以部分拷貝
var a = [1,2,3,4,5] var b = a.slice(1, 3) //返回[1,3)下標(biāo)區(qū)間的數(shù) console.log(b) //Array(2) [2, 3] //負(fù)數(shù)也可以 console.log(a.slice(-2)) //Array(2) [4, 5]
還有一種方法,跟循環(huán)的方法有點(diǎn)類似,就是es6的新特性,展開語法:
var a = [1,2,3,4,5] var b = [...a] b[0] = 0 console.log(a) //Array(5) [1, 2, 3, 4, 5]
這個(gè)方法就是逐一枚舉a中的值,放到空數(shù)組中
但是,以上這幾種拷貝方法看似都不會(huì)改變原來數(shù)組,其實(shí)也還是屬于淺拷貝范疇。如果原數(shù)組里面還有引用類型數(shù)組,這些方法都會(huì)失效(比如二維數(shù)組)
var a = [[1,2,3],[4,5,6]] var b = a.slice(0) b[0][4] = 0 console.log(a[0]) //[[1, 2, 0],[4,5,6]]
其他concat,[...]等方法也一樣。
可以這么理解:原數(shù)組就像一個(gè)帶鎖的獨(dú)一無二的箱子,里面有各種零食。簡單的引用復(fù)制,其實(shí)就是配了一把鑰匙,誰動(dòng)過里面的東西,其他人都會(huì)受到影響。而上面這4種方法其實(shí)就是自己買一個(gè)不同箱子,參照原來的箱子里面的零食,去某寶買同款。動(dòng)自己箱子的東西,原來的箱子不受影響。但是如果原來的箱子里面還套了個(gè)獨(dú)一無二帶鎖的箱子,某寶買不到同款,那沒辦法,里面的箱子只能還是配把鑰匙共用。所以,這4種方法只是簡單繞過第一層箱子的引用復(fù)制
深拷貝
目前比較好的方法就是json大法JSON.stringify(),要么就是自己寫遞歸的深拷貝函數(shù)。
JSON.stringify()是將對象或數(shù)組序列化成字符串。然后再用JSON.parse()解析成值或?qū)ο蟆?/p>
var a = {aa:1,bb:[1,2],cc:[3,4]} var b = JSON.parse(JSON.stringify(a)) console.log(b) //{aa:1,bb:[1,2],cc:[3,4]} b.cc[0] = 0 console.log(a) //{aa:1,bb:[1,2],cc:[3,4]} console.log(b) //{aa:1,bb:[1,2],cc:[0,4]}
附帶深拷貝的自定義函數(shù)(源自大佬mqyqingfeng的github)
var deepCopy = function(obj) { if (typeof obj !== "object") return; var newObj = obj instanceof Array ? [] : {}; for (var key in obj) { if (obj.hasOwnProperty(key)) { newObj[key] = typeof obj[key] === "object" ? deepCopy(obj[key]) : obj[key]; } } return newObj; }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/96348.html
摘要:在中可以通過添加一個(gè)參數(shù)來實(shí)現(xiàn)遞歸,調(diào)用就可以實(shí)現(xiàn)一個(gè)深拷貝。利用序列化實(shí)現(xiàn)一個(gè)深拷貝 在JavaScript中,對于Object和Array這類引用類型值,當(dāng)從一個(gè)變量向另一個(gè)變量復(fù)制引用類型值時(shí),這個(gè)值的副本其實(shí)是一個(gè)指針,兩個(gè)變量指向同一個(gè)堆對象,改變其中一個(gè)變量,另一個(gè)也會(huì)受到影響。 這種拷貝分為兩種情況:拷貝引用和拷貝實(shí)例,也就是我們說的淺拷貝和深拷貝 淺拷貝(shallow...
摘要:說明外層數(shù)組拷貝的是實(shí)例說明元素拷貝是引用深拷貝在堆中重新分配內(nèi)存,并且把源對象所有屬性都進(jìn)行新建拷貝,拷貝后的對象與原來的對象完全隔離,互不影響。中的方法可以實(shí)現(xiàn)深拷貝,源碼原理也是遞歸使用淺拷貝。 1.淺拷貝 當(dāng)把數(shù)組或?qū)ο蠛唵钨x值給其他變量的時(shí)候,實(shí)際上進(jìn)行的是淺拷貝,淺拷貝是拷貝引用,只是將拷貝后的引用指向同一個(gè)對象實(shí)例,彼此間的操作還會(huì)互相影響。 分為兩種情況:直接拷貝源對象...
摘要:而大多數(shù)實(shí)際項(xiàng)目中,我們想要的結(jié)果是兩個(gè)變量初始值相同互不影響。所以就要使用到拷貝分為深淺兩種深淺拷貝的區(qū)別淺拷貝只復(fù)制一層對象的屬性,而深拷貝則遞歸復(fù)制了所有層級。 為什么會(huì)用到淺拷貝和深拷貝 首先來看一下如下代碼 let a = b = 2 a = 3 console.log(a) console.log(b) let c = d = [1,2,3] let e = f = {a:...
摘要:而大多數(shù)實(shí)際項(xiàng)目中,我們想要的結(jié)果是兩個(gè)變量初始值相同互不影響。所以就要使用到拷貝分為深淺兩種深淺拷貝的區(qū)別淺拷貝只復(fù)制一層對象的屬性,而深拷貝則遞歸復(fù)制了所有層級。 為什么會(huì)用到淺拷貝和深拷貝 首先來看一下如下代碼 let a = b = 2 a = 3 console.log(a) console.log(b) let c = d = [1,2,3] let e = f = {a:...
摘要:而大多數(shù)實(shí)際項(xiàng)目中,我們想要的結(jié)果是兩個(gè)變量初始值相同互不影響。所以就要使用到拷貝分為深淺兩種深淺拷貝的區(qū)別淺拷貝只復(fù)制一層對象的屬性,而深拷貝則遞歸復(fù)制了所有層級。 為什么會(huì)用到淺拷貝和深拷貝 首先來看一下如下代碼 let a = b = 2 a = 3 console.log(a) console.log(b) let c = d = [1,2,3] let e = f = {a:...
閱讀 3631·2021-11-22 09:34
閱讀 3198·2021-11-15 11:38
閱讀 3078·2021-10-27 14:16
閱讀 1263·2021-10-18 13:35
閱讀 2437·2021-09-30 09:48
閱讀 3439·2021-09-29 09:34
閱讀 1662·2019-08-30 15:54
閱讀 1830·2019-08-26 11:57