摘要:引用類型值引用類型值是保存在堆內(nèi)存中的對象,變量保存的只是指向該內(nèi)存的地址,在復制引用類型值的時候,其實只復制了指向該內(nèi)存的地址。
前言
要理解 JavaScript中淺拷貝和深拷貝的區(qū)別,首先要明白JavaScript的數(shù)據(jù)類型。JavaScript有兩種數(shù)據(jù)類型,基礎數(shù)據(jù)類型和引用數(shù)據(jù)類型。
js的基本類型:undefined,null,string,boolean,number,symbol(es6新增),保存在棧內(nèi)存中
js的引用類型:Object類型, Array類型,Date類型,RegExp類型,F(xiàn)unction類型,基本包裝對象(Boolean類型,Number類型,String類型),單體內(nèi)置對象(Global對象,Math對象),保存在堆內(nèi)存空間中
1.1基本類型值
基本類型值是指在棧內(nèi)存保存的簡單數(shù)據(jù)段,在復制基本類型值的時候,會開辟出一個新的內(nèi)存空間,將值復制到新的內(nèi)存空間。
var a = 1; var b = a; a = 2; console.log(a);//輸出2; console.log(b);//輸出1;
var a = 1;
var b = a;
a = 2;
從上面例子看出,當一個變量的值是基本類型,把它復制給另一個變量,復制完成后改變它的值,不會影響已經(jīng)復制了它的值的變量。
1.2引用類型值
引用類型值是保存在堆內(nèi)存中的對象,變量保存的只是指向該內(nèi)存的地址,在復制引用類型值的時候,其實只復制了指向該內(nèi)存的地址。
var a = { name: "Kitty", age: "20", sex: "man" }; var b = a; a.name = "Jack"; console.log(a);//輸出{name: "Jack",age: 20,sex: "man"} console.log(b);//輸出{name: "Jack",age: 20,sex: "man"}
var a = {name: ‘Kitty’,age: ‘20’,sex: ‘man’};
var b = a;
a.name = ‘Jack’;
從上面例子看出,當一個變量的值是引用類型值,把它復制給另外一個變量,復制的只是指向儲存對象內(nèi)存的地址,所以復制完成后,改變它的值,會影響復制了它的值的變量。
注意:如果有兩個變量的值是引用類型值,就算它們的值完全相同,它們也是不相等的,因為它們指向的內(nèi)存地址不同,例子:
當一個變量是對象,如果像上面那樣直接將一個變量賦值給另一個變量,如果改變某個變量的值,另外一個變量也會跟著改變,如果我們不想發(fā)生這種情況,就需要寫一個函數(shù)用來拷貝對象。
深拷貝和淺拷貝的示意圖大致如下:
2.1 對象淺拷貝
var a = {name:"wanger"} var b = Object.assign({}, a) a===b // false b.name = "zhangsan" a.name //"wanger"
上面代碼將原始對象拷貝到一個空對象,就得到了原始對象的克隆,這時候a與b指向的是不同的棧對象,所以對b.name重新復制也不會影響到a.name。但是如果a.name是一個對象的引用,而不是一個字符串,那么上面的代碼也會遇到一些問題,參考如下代碼:
var a = {name:{firstName:"wang",lastName:"er"}} var b = Object.assign({}, a) a===b // false b.name.firstName = "zhang" a.name.firstName //"zhang"
b.name.firstName又影響到了a.name.firstName,這是因為Object.assign()方法只是淺層拷貝,a.name是一個棧對象的引用,賦值給b時,b.name也同樣是這個棧對象的引用,很多時候,我們不想讓這種事情發(fā)生,所以我們就需要用到對象的深拷貝。
2.2 對象深拷貝
2.2.1 萬能的for循環(huán)實現(xiàn)對象的深拷貝
var obj = { name: "FungLeo", sex: "man", old: "18" } var obj2 = copyObj(obj) function copyObj(obj) { let res = {} for (var key in obj) { res[key] = obj[key] } return res }
2.2.2 JSON.parse(JSON.stringify(objectToClone))
var obj = { name: "FungLeo", sex: "man", old: "18" } var obj2 = JSON.parse(JSON.stringify(obj))
2.2.3 擴展運算符實現(xiàn)對象的深拷貝
var obj = { name: "FungLeo", sex: "man", old: "18" } var { ...obj2 } = obj obj.old = "22" console.log(obj) console.log(obj2)
運行結果如下:
3.1 數(shù)組淺拷貝
var arr = ["old", 1, true, null, undefined]; var new_arr = arr.concat(); // 或者var new_arr = arr.slice()也是一樣的效果; new_arr[0] = "new"; console.log(arr); // ["old", 1, true, null, undefined] console.log(new_arr); // ["new", 1, true, null, undefined]
數(shù)組的淺拷貝,可用concat、slice返回一個新數(shù)組的特性來實現(xiàn)拷貝,但是如果數(shù)組嵌套了對象或者數(shù)組的話用concat、slice拷貝只要有修改會引起新舊數(shù)組都一起改變了,比如:
var arr = [{old: "old"}, ["old"]]; var new_arr = arr.concat(); arr[0].old = "new"; new_arr[1][0] = "new"; console.log(arr); // [{old: "new"}, ["new"]] console.log(new_arr); // [{old: "new"}, ["new"]]
如果數(shù)組元素是基本類型,就會拷貝一份,互不影響,而如果是對象或者數(shù)組,就會只拷貝對象和數(shù)組的引用,這樣我們無論在新舊數(shù)組進行了修改,兩者都會發(fā)生變化。這種叫淺拷貝 。
深拷貝就是指完全的拷貝一個對象,即使嵌套了對象,兩者也相互分離,修改一個對象的屬性,也不會影響另一個。
3.2 數(shù)組深拷貝
3.2.1 利用擴展運算符...對數(shù)組中嵌套對象進行深拷貝
var arr=[{a:1,b:2},{c:1,d:2}]; var arr2=[]; arr.forEach(item=>{ var {...obj}=item; arr2.push(obj); }) arr2[1].d=7 console.log(arr,arr2)
3.2.2 利用lodash庫的cloneDeep方法
var arr=[{a:1,b:2},{c:1,d:2}]; var arr2=_.cloneDeep(arr) arr2[1].d=7; console.log(arr,arr2)
3.2.3 JSON.parse(JSON.stringify(objectToClone))
var arr=[{a:1,b:2},{c:1,d:2}]; var arr2=JSON.parse(JSON.stringify(arr)); arr2[1].d=7; console.log(arr,arr2)
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/108613.html
摘要:在中可以通過添加一個參數(shù)來實現(xiàn)遞歸,調(diào)用就可以實現(xiàn)一個深拷貝。利用序列化實現(xiàn)一個深拷貝 在JavaScript中,對于Object和Array這類引用類型值,當從一個變量向另一個變量復制引用類型值時,這個值的副本其實是一個指針,兩個變量指向同一個堆對象,改變其中一個變量,另一個也會受到影響。 這種拷貝分為兩種情況:拷貝引用和拷貝實例,也就是我們說的淺拷貝和深拷貝 淺拷貝(shallow...
摘要:但是進行的是淺拷貝,拷貝的是屬性值。對象展開符深拷貝的實現(xiàn)方式手動復制轉成再轉回來只有可以轉成格式的對象才可以這樣用,像沒辦法轉成沒被改到使用方法避免相互引用對象導致死循環(huán),如的情況四參考關于的淺拷貝和深拷貝 一、理解 淺拷貝只復制指向某個對象的指針,而不復制對象本身,新舊對象還是共享同一塊內(nèi)存。但深拷貝會另外創(chuàng)造一個一模一樣的對象,新對象跟原對象不共享內(nèi)存,修改新對象不會改到原對象。...
摘要:說明外層數(shù)組拷貝的是實例說明元素拷貝是引用深拷貝在堆中重新分配內(nèi)存,并且把源對象所有屬性都進行新建拷貝,拷貝后的對象與原來的對象完全隔離,互不影響。中的方法可以實現(xiàn)深拷貝,源碼原理也是遞歸使用淺拷貝。 1.淺拷貝 當把數(shù)組或對象簡單賦值給其他變量的時候,實際上進行的是淺拷貝,淺拷貝是拷貝引用,只是將拷貝后的引用指向同一個對象實例,彼此間的操作還會互相影響。 分為兩種情況:直接拷貝源對象...
摘要:原文地址淺拷貝和深拷貝只針對像這樣的復雜對象的簡單來說,淺拷貝只拷貝一層對象的屬性,而深拷貝則遞歸拷貝了所有層級。淺拷貝通過來實現(xiàn)淺拷貝。 原文地址:http://www.silenceboy.com/201... 淺拷貝和深拷貝只針對像Object, Array這樣的復雜對象的.簡單來說,淺拷貝只拷貝一層對象的屬性,而深拷貝則遞歸拷貝了所有層級。 淺拷貝 通過 Object.ass...
摘要:而大多數(shù)實際項目中,我們想要的結果是兩個變量初始值相同互不影響。所以就要使用到拷貝分為深淺兩種深淺拷貝的區(qū)別淺拷貝只復制一層對象的屬性,而深拷貝則遞歸復制了所有層級。 為什么會用到淺拷貝和深拷貝 首先來看一下如下代碼 let a = b = 2 a = 3 console.log(a) console.log(b) let c = d = [1,2,3] let e = f = {a:...
閱讀 1392·2021-10-19 11:42
閱讀 731·2021-09-22 16:04
閱讀 1882·2021-09-10 11:23
閱讀 1862·2021-07-29 14:48
閱讀 1261·2021-07-26 23:38
閱讀 2821·2019-08-30 15:54
閱讀 1037·2019-08-30 11:25
閱讀 1703·2019-08-29 17:23