說起深淺拷貝,我覺得需要理清楚 值類型
和 引用類型,本文主要和大家分享js實現深淺拷貝方法,希望能幫助到大家。
所謂值型別
是undefined
,null
,number
, string
,boolean
等五種基本資料類型, 應該還有一個Symbol
類型。
值類型的資料儲存在堆疊記憶體中
在值類型
中修改值相當於重新在堆疊記憶體中開闢了一個新的儲存空間,類似:
用程式碼解釋就是:
var num1 = 5var num2 = num1
值類型的值不可改變
javascript中的原始值(undefined、null、布林值、數字和字串)與物件(包括陣列和函數)有著根本區別。原始值是不可更改的:任何方法都無法更改(或“突變”)一個原始值。對數字和布林值來說顯然如此—— 改變數字的值本身就說不通,而對字串來說就不那麼明顯了,因為字串看起來像由字元組成的數組,我們期望可以透過指定索引來假改字串中的字元。實際上,javascript 是禁止這樣做的。字串中所有的方法看上去回傳了一個修改過的字串,實際上回傳的是一個新的字串值。
var str = 'abc'str[0] = 'd'console.log(str) // 'abc'
值類型的比較是對值的比較
值類型的比較是值的比較,只要它們的值相等就認為他們是相等的
var a = 1;var b = 1;console.log(a === b);//true
引用型別的資料存放在堆疊記憶體中
引用型別的值存放在堆疊記憶體中,變數保存的是一個存放在堆疊內存,指向堆記憶體的指標。
var person1 = {name:'jozo'};var person2 = {name:'xiaom'};var person3 = {name:'xiaoq'};
引用類型的值可以改變
引用類型是可以直接改變其值的
var a = [1,2,3]; a[1] = 5; console.log(a[1]); // 5
引用類型的比較是引用的比較
所以每次我們對js 中的引用類型進行操作的時候,都是操作其物件的參考(保存在堆疊記憶體中的指標),所以比較兩個引用類型,是看其的引用是否指向同一個物件。
var a = [1,2,3];var b = [1,2,3];console.log(a === b); // falsevar a = [1, 2, 3]var b = aconsole.log(a === b) // true
了解了基本資料型別與參考型別的差異之後,我們就應該可以明白傳值與傳址的差異了。
在我們進行賦值操作的時候,基本資料型別的賦值(=)是在記憶體中新開闢一段堆疊內存,然後再把再將值賦值到新的棧中
var a = 10;var b = a; a ++ ; console.log(a); // 11console.log(b); // 10
所以說,基本類型的賦值的兩個變數是兩個獨立相互不影響的變數。
但是引用型別的賦值是傳址。只是改變指標的指向,例如,也就是說引用類型的賦值是物件保存在堆疊中的位址的賦值,這樣的話兩個變數就指向同一個對象,因此兩者之間操作互相有影響。
var a = {}; // a保存了一个空对象的实例var b = a; // a和b都指向了这个空对象a.name = 'jozo'; console.log(a.name); // 'jozo'console.log(b.name); // 'jozo'b.age = 22; console.log(b.age);// 22console.log(a.age);// 22console.log(a == b);// true
實作:
function shallowCopy (src) { let new = {} for (let i in src) { if (src.hasOwnProperty(i)) { new[i] = src[i] } } return new}
一種騷操作是利用JSON.parse 和JSON.stringify
var a = { name: 'SpawN', age: 28}var b = JSON.parse(JSON.stringify(a)) b.name = 'Johnny.R'console.log(a.name) // 'SpawN'
另外一種是科班操作,也就是常規操作,就是利用遞歸,來遍歷目標對像下的所有屬性
function deepCopy(obj) { if (typeof obj !== 'object') return // 初始化 var newObj = obj instanceof Array ? [] : {} for (let k in obj) { if (obj.hasOweProperty(k)) { newObj[k] = typeof obj[k] === 'object' ? agruments.callee(obj[k]) : obj[k] } } return newObj }
這裡只是實現了基本的深拷貝,對一些邊界並沒有進行妥善的處理。基本想法就是透過for in 循環,當值為物件的時候,再遞歸進行for in迴圈。
相關推薦:
#以上是js實作深淺拷貝方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!