摘要:拷貝分為淺拷貝和深拷貝。淺拷貝是引用復制,深拷貝是完全單純拷貝數據的值。所以,這種方法只是簡單繞過第一層箱子的引用復制深拷貝目前比較好的方法就是大法,要么就是自己寫遞歸的深拷貝函數。附帶深拷貝的自定義函數源自大佬的
經常遇到數組或對象等引用類型作為函數的參數的情況,但又不想修改原來的數據,這時候就需要拷貝(基本類型的變量不需要考慮)。
拷貝分為淺拷貝和深拷貝。淺拷貝是引用復制,深拷貝是完全單純拷貝數據的值。因為數組是最常見的引用類型,所以下面大部分拿數組舉例。
淺拷貝
簡單把引用復制
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]
可以看出,修改數組b的時候,數組a也被修改了。這顯然不是想要的做法。
要想不改變原來的數組,就要用到以下的幾種方法:
循環 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)下標區間的數 console.log(b) //Array(2) [2, 3] //負數也可以 console.log(a.slice(-2)) //Array(2) [4, 5]
還有一種方法,跟循環的方法有點類似,就是es6的新特性,展開語法:
var a = [1,2,3,4,5] var b = [...a] b[0] = 0 console.log(a) //Array(5) [1, 2, 3, 4, 5]
這個方法就是逐一枚舉a中的值,放到空數組中
但是,以上這幾種拷貝方法看似都不會改變原來數組,其實也還是屬于淺拷貝范疇。如果原數組里面還有引用類型數組,這些方法都會失效(比如二維數組)
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,[...]等方法也一樣。
可以這么理解:原數組就像一個帶鎖的獨一無二的箱子,里面有各種零食。簡單的引用復制,其實就是配了一把鑰匙,誰動過里面的東西,其他人都會受到影響。而上面這4種方法其實就是自己買一個不同箱子,參照原來的箱子里面的零食,去某寶買同款。動自己箱子的東西,原來的箱子不受影響。但是如果原來的箱子里面還套了個獨一無二帶鎖的箱子,某寶買不到同款,那沒辦法,里面的箱子只能還是配把鑰匙共用。所以,這4種方法只是簡單繞過第一層箱子的引用復制
深拷貝
目前比較好的方法就是json大法JSON.stringify(),要么就是自己寫遞歸的深拷貝函數。
JSON.stringify()是將對象或數組序列化成字符串。然后再用JSON.parse()解析成值或對象。
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]}
附帶深拷貝的自定義函數(源自大佬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; }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/96348.html
摘要:在中可以通過添加一個參數來實現遞歸,調用就可以實現一個深拷貝。利用序列化實現一個深拷貝 在JavaScript中,對于Object和Array這類引用類型值,當從一個變量向另一個變量復制引用類型值時,這個值的副本其實是一個指針,兩個變量指向同一個堆對象,改變其中一個變量,另一個也會受到影響。 這種拷貝分為兩種情況:拷貝引用和拷貝實例,也就是我們說的淺拷貝和深拷貝 淺拷貝(shallow...
摘要:說明外層數組拷貝的是實例說明元素拷貝是引用深拷貝在堆中重新分配內存,并且把源對象所有屬性都進行新建拷貝,拷貝后的對象與原來的對象完全隔離,互不影響。中的方法可以實現深拷貝,源碼原理也是遞歸使用淺拷貝。 1.淺拷貝 當把數組或對象簡單賦值給其他變量的時候,實際上進行的是淺拷貝,淺拷貝是拷貝引用,只是將拷貝后的引用指向同一個對象實例,彼此間的操作還會互相影響。 分為兩種情況:直接拷貝源對象...
摘要:而大多數實際項目中,我們想要的結果是兩個變量初始值相同互不影響。所以就要使用到拷貝分為深淺兩種深淺拷貝的區別淺拷貝只復制一層對象的屬性,而深拷貝則遞歸復制了所有層級。 為什么會用到淺拷貝和深拷貝 首先來看一下如下代碼 let a = b = 2 a = 3 console.log(a) console.log(b) let c = d = [1,2,3] let e = f = {a:...
摘要:而大多數實際項目中,我們想要的結果是兩個變量初始值相同互不影響。所以就要使用到拷貝分為深淺兩種深淺拷貝的區別淺拷貝只復制一層對象的屬性,而深拷貝則遞歸復制了所有層級。 為什么會用到淺拷貝和深拷貝 首先來看一下如下代碼 let a = b = 2 a = 3 console.log(a) console.log(b) let c = d = [1,2,3] let e = f = {a:...
摘要:而大多數實際項目中,我們想要的結果是兩個變量初始值相同互不影響。所以就要使用到拷貝分為深淺兩種深淺拷貝的區別淺拷貝只復制一層對象的屬性,而深拷貝則遞歸復制了所有層級。 為什么會用到淺拷貝和深拷貝 首先來看一下如下代碼 let a = b = 2 a = 3 console.log(a) console.log(b) let c = d = [1,2,3] let e = f = {a:...
閱讀 3624·2021-11-22 09:34
閱讀 3194·2021-11-15 11:38
閱讀 3065·2021-10-27 14:16
閱讀 1248·2021-10-18 13:35
閱讀 2436·2021-09-30 09:48
閱讀 3437·2021-09-29 09:34
閱讀 1654·2019-08-30 15:54
閱讀 1828·2019-08-26 11:57