前言:2019年的第一篇分享... 一、什麼是基本類型值和引用類型值?ECMAScript包括兩個不同類型的值:基本數據類型和引用數據類型。基本數據類型指的是簡單的數據段,引用數據類型指的是有多個值構成的對象。當我們把變數賦值給一個變數時,解析器首先要確認的就是這個值是基本類型值還是引用類型值。 註 ...
前言:2019年的第一篇分享...
一、什麼是基本類型值和引用類型值?
ECMAScript包括兩個不同類型的值:基本數據類型和引用數據類型。
基本數據類型指的是簡單的數據段,引用數據類型指的是有多個值構成的對象。
當我們把變數賦值給一個變數時,解析器首先要確認的就是這個值是基本類型值還是引用類型值。
註:要瞭解深拷貝和淺拷貝,首先要先理解ECMAScript中的數據類型,其中基本類型值(如undefined、null、number、string、boolean以及es6新增的Symbol), 還有一些引用類型值(如對象)。
淺拷貝和深拷貝一般是對於引用類型值(如對象)來講的,而基本類型值,只要是複製,就一定是另開闢以存儲空間。
1 // 示例1(基本類型值)) 2 var a = 10; 3 var b = a; 4 b = 20; 5 console.log(b); //輸出 20 6 console.log(a); //輸出 10
// 類似示例1,基本類型在拷貝的時候,b改變了,但是並不會印象到a。
1 // 示例2(引用類型值) 2 var obj_a = { a: 10, b: 20 }; 3 var obj_b = obj_a; 4 obj_b.a = 30; 5 console.log(obj_b); //輸出 { a: 30, b: 20 } 6 console.log(obj_a); //輸出 { a: 30, b: 20 } 7 8 // 類似示例2,複雜類型在拷貝的時候,然後改變了obj_b的屬性的值,但是卻改變了obj_a的,很明顯,這個結果並不是我們想要的,其實他們還是指向同一個對象,只是展示視窗的位置不同而已。
1 // 示例3(應用類值&深拷貝) 2 var obj_a = { a: 10, b: 20, c: 30 }; 3 var obj_b = { a: obj_a.a, b: obj_a.b, c: obj_a.c }; 4 obj_b.a = 40; 5 console.log(obj_b); //輸出 { a: 40, b: 20, c: 30 } 6 console.log(obj_a); //輸出 { a: 10, b: 20, c: 30 } 7 8 // 類似示例3,複雜類型在拷貝的時候,然後改變了obj_b的屬性的值,但是卻沒有改變了obj_a的,因為在拷貝的時候,其實是相當於新建了一個領地,然後遍歷舊對象的每一項的值,在新對象裡面新建每一項,然後把對應的值複製進去,他們是不同的對象,這就是所謂的深拷貝。
二、淺拷貝和深拷貝的原理
1.基本數據類型值( 基本數據類型值的名和值都存在棧記憶體裡面 )
如:let a = 1; 如圖:
當let b = a,b複製了a,棧記憶體會另外開闢一塊地方存放b的名值,如圖:
兩者互不幹涉,誰也沒有影響到誰。
2.引用數據類型值( 引用數據類型值棧記憶體裡面存值的位置則存放的是a的值在堆記憶體裡面的位置,也就是唯一堆地址 )
如:let a = [ 0, 1, 2, 3, 4 ];如圖:
當let b = a,b複製了a,b引用了a的堆地址。如圖:
所以這個時候,改變了b,a也會受到影響。
三、實現深拷貝
層級拷貝,遞歸方式(其實就是函數的自我調用)
何為層級?如,var a = [0,1,[3,4],3]; 數組嵌套著數組。
實現方法:
// 代碼中加入判斷,當碰到數組、對象等時遞歸函數
1 function deepClone(obj){ 2 //定義對象來判斷當前的參數是數組還是對象 3 let objClone = Array.isArray(obj)?[]:{}; 4 //如果obj存在並且為對象 5 if(obj&&typeof obj == "object"){ 6 for(let key in obj){ 7 if(obj.hasOwnProperty(key)){ 8 //如果obj的子元素為對象,那麼遞歸(層級遍歷) 9 if(obj[key]&&typeof obj[key] == "object"){ 10 objClone[key] = deepClone(obj[key]); 11 }else{ 12 //如果不是,直接賦值 13 objClone[key] = obj[key]; 14 } 15 } 16 } 17 } 18 return objClone; 19 }
利用 jeury.extend() 淺拷貝&深拷貝
$.extend( [deep ], target, object1 [, objectN ] )
註:deep表示是否深拷貝,為true為深拷貝,為false,則為淺拷貝
target Object類型 目標對象,其他對象的成員屬性將被附加到該對象上。
object1 objectN可選。 Object類型 第一個以及第N個被合併的對象。
1 let a = [0, 1, [2, 3], 4], 2 b = $.extend(true, [], a); 3 a[0] = 1; 4 a[2][0] = 1; 5 console.log(a, b);
通過ES6的concat()
方法
concat()
用於合併兩個或多個數組。此方法不會更改現有數組,而是返回一個新數組。
1 var a = [1,2,3] 2 var b = a.concat(); 3 b[2] =10; 4 console.log(a
上面這個情況a的值並沒有改變。
以上就是我的一些個人的理解和靖藏使用的一些深拷貝的處理方法,僅供參考。