一文看懂 ES6 解構賦值

一、什麼是解構賦值

ES6中,通過解構賦值,可以將屬性 / 值對象 / 數組中取出,賦值給其他變量的操作就是解構賦值。

在下圖上可以發現左側和右側都必須是數組,左側可以定義 n 個變量,那麼與之對應的右側也需要有相應個數的變量值,我們左側的變量從右側取值的操作就是解構賦值

二、數組解構

在上面的圖示裏可以看出來,數組解構就是從數組中提取值,只要等號兩邊的模式相同,左邊的變量就會在右側的數組裏查找對應位置的值進行賦值操作。

數組結構的應用主要有:

  • 對一維數組解構

  • 對多維數組解構

  • 對字符串解構

  • 對...擴展運算符解構

1. 一維數組解構

傳統的變量賦值是這樣的:

let arr = [1,2,3];//把數組的值分別賦給下面的變量;
let a = arr[0];
let b = arr[1];
let c = arr[2];

console.log(a); // a的值爲1
console.log(b); // b的值爲2
console.log(c); // c的值爲3

變量的解構賦值:

let [a,b,c] = [1,2,3];  //把數組的值分別賦給下面的變量;
console.log(a); // a的值爲1
console.log(b); // b的值爲2
console.log(c); // c的值爲3

左側是數組,右側也是數組。

左側的變量會根據索引,依次獲取右側數組裏的值。

代碼短了很多,可讀性也很強,這種叫做數組的解構賦值

一句話:按索引取值~!

  • 不完全解構

    當左邊的模式(你可以理解爲格式)與右邊不完全一樣的時候,那麼賦值過程中,只會給模式匹配成功的部分的變量賦值。

    • 沒得到的值的變量,返回的就是 undefined。相當於只聲明瞭變量,但是沒賦值。

    • 沒有變量存儲的值,就會被浪費掉。

let [a] = [];      // a = undefined  

let [name,age,add] = ["Lily", , "Chongqing"];
console.info( name );  // Lily
console.info( age );   // undefined
console.info( add );   // Chongqing
let [x, , z] = [1, 2, 3];   //x=1,z=3  

// 傳統寫法
let arr = [1, 2, 3];
let x = arr[0];
let z = arr[2];
  • 左側變量可以設定默認值

如果變量的值取到了 undefined ,那麼左側變量返回的就是默認值。否則,就是右側設定的值。

let [name="Lily",age=18] = [ "Mouse",  20 ] ;   //  age = 20 

let [name="Lily",age=18] = [ "Mouse",  0 ] ;   //  age = 0 
let [name="Lily",age=18] = [ "Mouse",  NaN ] ;   //  age = NaN 
let [name="Lily",age=18] = [ "Mouse",  null ] ;   //  age = null 

let [name="Lily",age=18] = [ "Mouse" ] ;   //  age = 18 
let [name="Lily",age=18] = [ "Mouse" , undefined ] ;   //  age = 18 
  • 可以用來交換變量數據
let a = 1;
let b = 2;
[a,b] = [b,a];
console.info(a,b);  // 2 1

2. 多維數組結構

let arr1 = [1,[2,3],4];
let [a1, [b1,c1,d1], e1] = arr1; 
console.info( a1,b1,c1,d1,e1);  // 1,2,3,undefined,4

按照索引對應就行。

如果兩側不一致:

let [a,b,c] = [1,[2,3]];
console.log(a,b,c); // 1 [2, 3] undefined

從這裏可以看出,結構賦值其實就是一種模式匹配,兩邊模式要一致纔行。

3. 字符串解構

字符串也可以這麼玩,因爲字符串的字符也是有索引的。在解構賦值的過程中,字符串被轉換成了一個類似數組的對象。

// 證明字符串有索引
let str = "hello";
console.info( str[0] );  // h
console.info( str[1] );  // e
// 字符串解構
let str = "hello";
let [a,b, , ,c] = str ;
console.info( a,b,c);  // h e o

4. 拓展運算符(...)

也稱爲擴展運算符 ,就是三個連續的點(...)。

作用:取出參數對象中可遍歷的屬性,拷貝到當前對象之中。(百度出來的)

我的個人理解是:可以把數組轉爲數據序列。

  • 函數參數

function add(x, y) {   // 參數 x,y 是個數據序列,逗號隔開。
  return x + y;
}

let numbers = [4, 10]; // 數組
add(...numbers); // 14。 把數組轉爲數據序列,可以作爲函數的參數。
  • 複製數組
// 複製數組
let arr1 = [1, 2];
let arr2 = arr1;   // 數組是引用數據類型。arr1,arr2 都指向同一個數組空間。
					 // 一個數據改了,另一個數據也改了
arr2[0] = 2;
console.info(arr1) // [2, 2]  ,複製失敗

// 用 ... 拓展運算符就可以複製數組
let arr1 = [1, 2];
let arr2 = [...arr1];
arr2[0] = 2 ;
console.info( arr1 );  // [1, 2]  ,複製成功。arr1 不受 arr2 數據變化影響。
  • 數組合並
// 傳統做法
let arr = [1,2,3];
let newarr = [4, 5].concat(arr); // 用concat連接兩個數組,返回一個新的數組副本

// ES6 拓展運算符
let arr = [1,2,3];
let newArr1 = [4, 5,...arr];
let newArr2 = [4, ...arr , 5];
console.info( newArr1 );  // [4, 5, 1, 2, 3]
console.info( newArr2 );  // [4, 1, 2, 3, 5]
  • 與數組結構一起用

用於生成數組

let [first, ...rest] = [1, 2, 3, 4, 5];
console.info( first ); // 1
console.info( rest  ); // [2, 3, 4, 5]

如果將擴展運算符用於數組賦值,只能放在參數的最後一位,否則會報錯。

let [...rest, last] = [1, 2, 3, 4, 5];
// 報錯
let [first, ...rest, last] = [1, 2, 3, 4, 5];
// 報錯
  • 將字符串轉爲真正的數組
let str = "hello";
let arr = [...str];
console.info( arr );  // ["h", "e", "l", "l", "o"]

三、對象解構

按照屬性來進行解構賦值,如果解構不成功,變量的值等於 undefined對象解構可以指定默認值。

1. 和數組解構的對比

  • 數組的元素是按次序排列的,變量的取值由它的位置決定;

  • 模式匹配,兩邊都必須是 Object 對象

  • 而對象的屬性沒有次序,變量必須與屬性同名,才能取到正確的值。

// 對象的解構賦值,跟順序沒有關係
let {age, name } = { name:"Tom", age:18 };
console.info(age,name);  // 18 , Tom

let { age:b, name:a } = { nam e:"Tom", age:18 };
console.info( b, a );    // 18 , Tom

左右屬性名不一致,會得到 undefined。

let {age, nameZ } = { name:"Tom", age:18 };
console.info(age,nameZ);  // 18 , undefined

let { age:b, nameZ:a } = { name:"Tom", age:18 };
console.info( b, a );    // 18 , undefined

對象解構語句不是以變量聲明關鍵字(如var,let或const)開頭,則需要將語句包裹在括號中。 否則會報錯。

 ({ a, b } = { a:100, b:200 }  ); // good
let { a, b } = { a:100, b:200 } ; // good

let  a , b ;
{ a, b } = { a:100, b:200 } ;   // 報錯

2. 對象解構默認值

// 變量的非 undefined 的值可以取到
let { name, age = 28 } = { name:"Tom", age:18 };
console.info( name, age );    // Tom , 18

// 變量取到了 undefined ,則返回默認值
let { name, age = 28 } = { name:"Tom" };
console.info( name, age );    // Tom , 28
let {name: a = "Tom", age: b = 28} = { name :"Lily"};
console.info( a, b );   // Lily, 28

// 右側一個值都沒有
let {name: a = "Tom", age: b = 28} = {};
console.info( a, b );   // Tom, 28

3. 對象作爲函數參數

Object 對象可以作爲函數參數。

let  addFun = function( obj ){
    let sum = obj.a + obj.b ;
    console.info( sum );
};
addFun({
    a:100,
    b:200
});  // 300 

爲了設置 a ,b 默認值。利用對象解構,設置形參

// 實參和形參會進行解構操作。
let  addFun = function( { a=100, b=100 } ){
    let sum = a + b ;
    console.info( sum );
};
addFun({
    a:100,
    b:200
});  // 300。a ,100 ; b,200

addFun({ a:50 });  // 150。a,50; b 被省略,取默認值 100 。
addFun({ });  // 200。a , b 均取默認值
addFun(); // Cannot read property 'a' of undefined

上面代碼只使用了對象的解構賦值默認值,沒有使用函數參數的默認值。只有當函數 addFun 的參數是一個對象時,變量 a 和 b 纔會通過解構賦值生成。

如果函數 addFun 調用時沒提供參數,變量 a 和 b 就不會生成,從而報錯。

addFun();  // 報錯。Uncaught TypeError: Cannot read property 'a' of undefined

相當於在執行代碼

{ a=100, b=100 } = undefined ; 

試圖對 undefined 進行對象結構,會報錯。

通過提供函數參數的默認值,就可以避免這種情況。

let  addFun = function( { a=100, b=100 } = {} ){
    let sum = a + b ;
    console.info( sum );
}; 
addFun( );  // 200。

參數默認值是 {} 。{} 會解構給 a,b 賦值。a,b 解構的值都是 undefined,所以取 a,b 均會獲取解構的默認值 100。

四、對非對象進行解構

如果解構的值爲 null、undefined,會得到一個類型錯誤提示。

如果你的值爲數字、布爾值、字符串,會得到一個 undefined。

如果等號左側的變量名爲 Object.prototype 上的方法名稱時,返回的就是方法實例。

let {a} = null ;   // 報錯
let {a} = undefined ;   // 報錯
let { age:a } = undefined ;   // 報錯

let {a} = 13 ;   // a = undefined

let { toString } = 123 ;  // toString() { [native code] }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章