【ES6基礎】解構賦值(destructuring assignment)

前端達人發表於2019-02-20
【ES6基礎】解構賦值(destructuring assignment)

我們經常可以在其他程式語言(如GO語言)中看到多返回值這種特性,因為在很多實際場景中,函式的返回值中,函式的返回值並不只有一個單一的值。ES6之前,並沒有可以直接使用語法來實現多返回值的特性。ES6終於出現瞭解構賦值的語法糖來解決此類問題。

解構賦值是一種表示式,允許您使用陣列或物件,將可迭代物件的值或屬性分配給變數。解構賦值能讓我們用更簡短的語法進行多個變數的賦值,大大的減少了程式碼量。解構表示式有兩種:array和object。

今天的文章筆者將從以下方面進行介紹:

  • 使用陣列表示式解構賦值
    • 常規用法
    • 忽略陣列中的某些值
    • 使用展開語法
    • 預設引數值
    • 巢狀陣列解構
    • 作為函式引數
  • 使用物件表示式解構賦值
    • 常規用法
    • 預設引數值
    • 巢狀物件
    • 作為函式引數
  • 其他
    • 解構物件的方法
    • 獲取字串長度
    • 拆分字串
    • 交換變數
    • 遍歷Map結構
    • 載入指定模組的方法
  • 常用場景介紹

本篇本章閱讀時間預計15分鐘

使用陣列表示式解構賦值

常規用法

如何將一個陣列的值,賦值給多個變數?陣列解構語法能讓我們快速的迭代陣列的元素,並賦值給多個變數。

E6之前,我們可以這種形式將陣列的內容賦值給多個變數:

var myArray = [1, 2, 3];
var a = myArray[0];
var b = myArray[1];
var c = myArray[2];複製程式碼

ES6後,我們可以通過陣列解構語法,在一行語句裡完成上述操作。

let myArray = [1, 2, 3];
let a, b, c;
[a, b, c] = myArray; //array destructuring assignment syntax複製程式碼

上述程式碼中,[a, b, c]就是解構表示式。在陣列解構語句的左側就是需要進行賦值的多個變數,等號右側則是我們需要分配的值。

我們還可以讓上述程式碼更短,你還可以這麼寫,程式碼如下:

let [a, b, c] = [1, 2, 3];

我們在同一行語句中建立變數,而不是分別建立。是不是更清爽。

如果左邊的數值少於右邊陣列的項數,左邊變數的值只會和右邊陣列的內容一一對應,多於的內容將會忽略。

忽略陣列中某些值

如果只有兩個變數,我們陣列內容有三項,我們想跳過陣列中的第二項,我們如何使用陣列解構賦值呢?程式碼如下:

let [a, , b] = [1, 2, 3];
console.log(a);
console.log(b);複製程式碼

上述程式碼我們使用, ,忽略陣列中的第二項,建議中間有空格,方便我們閱讀。

使用展開語法

上篇文章《【ES6基礎】展開語法(Spread syntax)》,筆者介紹了展開語法的幾個應用場景,由於上篇文章沒介紹解構賦值,所以在這裡給大家介紹展開語法在解構賦值的應用。如下段程式碼所示:

let [a, ...b] = [1, 2, 3, 4, 5, 6];
console.log(a);
console.log(Array.isArray(b));
console.log(b);”複製程式碼

上述程式碼則會輸出:

1
true
2,3,4,5,6複製程式碼

上述程式碼,你可以看到b變數被解構賦值成陣列,這裡...就是我們上篇文章提到的剩餘引數場景的運用。

如果想跳過陣列中的部分值,我們可以這麼做,如下段程式碼所示:

let [a, , ,...b] = [1, 2, 3, 4, 5, 6];
console.log(a);
console.log(b);複製程式碼

上述程式碼則會輸出:

1
456複製程式碼

這段程式碼我們跳過了陣列的第2項和第3項。

預設引數值

筆者在《【ES6基礎】預設引數值》給大家介紹瞭如何使用預設引數值,在解構賦值中,我們如何設定變數的預設值呢,如下段程式碼所示:

let [a, b, c = 3] = [1, 2];
console.log(c); //Output "3”複製程式碼

巢狀陣列

我們還可以從多維陣列中提取值並分配給變數,如下段程式碼所示:

let [a, b, [c, d]] = [1, 2, [3, 4]];複製程式碼

作為函式引數

我們還可以使用陣列解構表示式作為函式引數來提取可迭代陣列的值,作為引數傳遞給函式引數,如下段程式碼所示:

function myFunction([a, b, c = 3]) {
     console.log(a, b, c); //Output "1 2 3"
   }
myFunction([1, 2]);複製程式碼

筆者在《【ES6基礎】預設引數值》提及到我們可以傳遞undefined,指定某個具體的引數使用預設值,我們可以使用結構賦值為相關變數提供一組預設值,並傳入undefined,如下段程式碼所示:

function myFunction([a, b, c = 3] = [1, 2, 3]) {
     console.log(a, b, c);  //Output "1 2 3"
   }
myFunction(undefined);複製程式碼

在這裡,我們將undefined作為引數傳遞,因此使用預設陣列[1,2,3]進行提取賦值。

使用物件表示式解構賦值

常規用法

物件解構賦值將物件屬性的值賦給多個變數。ES6之前我們可以這樣把物件的屬性賦值給多個變數,如下段程式碼所示:

var object = {name : "John", age : 23};
var name = object.name;
var age = object.age;複製程式碼

在ES6裡,我們可以使用物件解構表示式,在單行裡給多個變數賦值,如下段程式碼所示:

let object = {name : "John", age : 23};
let name, age;
({name, age} = object); //object destructuring assignment syntax複製程式碼

物件解構賦值的左側為解構賦值表示式,右側為對應要分配賦值的物件。解構語句的兩邊千萬不要遺漏左右括號(),否則會報錯。

還有一點需要格外注意,解構物件變數的名稱一定要和右邊物件的屬性名稱保持一致,否則會提示變數的值為undefined。如果你想以其它的變數名進行命名,你可以這麼做,如下段程式碼所示:

let object = {name : "John", age : 23};
let x, y;
({name: x, age: y} = object);複製程式碼

上述程式碼x,y為對應物件屬性的值John,23。如果你輸出name或age,編譯器則會提示ReferenceError: 變數 is not defined

我們可以讓程式碼更短,如下段程式碼所示:

let {name: x, age: y} = {name : "John", age : 23};複製程式碼

上述程式碼由於宣告變數和解構賦值在同一行,因此物件解構語句兩邊無需左右括號()。

預設引數值

在解構物件針對未分配值的變數,我們可以為變數提供預設值,如下段程式碼所示:

let {a, b, c = 3} = {a: "1", b: "2"};
console.log(c); //Output "3”複製程式碼

在解構物件時變數名支援表示式計算,如下段程式碼所示:

let {["first"+"Name"]: x} = { firstName: "Eden" };
console.log(x); //Output "Eden”複製程式碼

巢狀物件

我們還可以從巢狀物件中提取屬性值,即物件中的物件。 如下段程式碼所示:

let {name, otherInfo: {age}} = {name: "Eden", otherInfo: {age:23}};
console.log(name, age); //Eden 23複製程式碼

作為函式引數

就像陣列解構賦值一樣,我們也可以使用物件解構賦值作為函式引數,如下段程式碼所示:

function myFunction({name = 'Eden', age = 23, profession ="Designer"} = {}){
    console.log(name, age, profession); // Outputs "John 23 Designer"
}
myFunction({name: "John", age: 23});複製程式碼

在這裡,我們傳遞一個空物件作為預設引數值,如果將undefined作為函式引數傳遞,變數將使用預設值。

其他

解構物件的方法

比如結構Math物件的方法,如下段程式碼所示:

let {floor,pow}=Math;//把Math裡的方法提取出來變成一個變數
let a=1.1;
console.log(floor(a));//1
console.log(pow(2,3));//8複製程式碼

獲取字串的長度

var {length}='lxy';
console.log(length);//3複製程式碼

拆分字串

var [a,b,c,d]='前端達人';
console.log(a,b,c,d) // 輸出:前 端 達 人複製程式碼

交換變數

let x = 1;
let y = 2;
[x, y] = [y, x];複製程式碼

遍歷Map結構

var map = new Map();
map.set('first', 'hello');
map.set('second', 'world');

for (let [key, value] of map) {
    console.log(key + " is " + value);
}複製程式碼

載入指定模組的方法

const { SourceMapConsumer, SourceNode } = require("source-map");複製程式碼

常用場景介紹

比如我們經常與後端API介面做資料互動,我們需要處理返回的JSON物件,使用解構方式大大簡化了我們的程式碼,如下段程式碼所示:

let jsonData = {
    id: 42,
    status: "OK",
    data: [867, 5309]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, "OK", [867, 5309]複製程式碼

小節

今天的內容有些多,想必大家對解構賦值有了全面的認識吧,使用解構賦值是不是很強大,大大簡化了我們的程式碼量,雖然優勢蠻多,但是增加對程式碼的理解難度,我們只有在實踐中不斷的運用,來加深我們對解構賦值的認識。

ES6相關文章

【ES6基礎】let和作用域

【ES6基礎】const介紹

【ES6基礎】預設引數值

【ES6基礎】展開語法(Spread syntax)

更多精彩內容,請微信關注”前端達人”公眾號!

【ES6基礎】解構賦值(destructuring assignment)

相關文章