1. 程式人生 > 實用技巧 >ECMAScript 6-變數的結構賦值

ECMAScript 6-變數的結構賦值

ES6 許按照一定模式,從陣列和物件中提取值,對變數進行賦值,這被稱為解構(Destructuring)

1.陣列解構賦值

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

let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3

let [ , , third] = ["foo", "bar", "baz"];
third // "baz"

let [x, , y] = [1, 2, 3];
x // 1
y // 3

let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]

let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []

預設值

let [foo = true] = [];
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'	

2.物件解構賦值

let { foo, bar } = { foo: "aaa", bar: "bbb" };

陣列的元素是按次序排列的,變數的取值由它的位置決定;而物件的屬性沒有次序,變數必須與屬性同名,才能取到正確的值

物件的解構賦值是下面形式的簡寫。物件的解構賦值的內部機制,是先找到同名屬性,然後再賦給對應的變數

。真正被賦值的是後者,而不是前者。前面的foo和bar是匹配模式,後面的才是變數,即冒號前面的都是匹配模式

let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };

變數的宣告和解構賦值的變數是一體的

let foo;
let {foo} = {foo: 1}; // SyntaxError: Duplicate declaration "foo"

圓括號可以理解成一個程式碼塊

let foo;
({foo} = {foo: 1}); // 成功

預設值

var {x = 3} = {};	x // 3
var {x, y = 5} = {x: 1};	x // 1		y // 5
var { message: msg = 'Something went wrong' } = {};		msg // "Something went wrong"
var {x = 3} = {x: undefined};	x // 3
var {x = 3} = {x: null};	x // null

字串的解構賦值

const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"

類似陣列的物件都有一個length屬性,因此還可以對這個屬性解構賦值

let {length : len} = 'hello';
len // 5

3.數值和布林值的解構賦值

如果等號右邊是數值和布林值,則會先轉為物件。數值和布林值的包裝物件都有toString屬性

let {toString: s} = 123;
s === Number.prototype.toString // true

let {toString: s} = true;
s === Boolean.prototype.toString // true

解構賦值的規則是,只要等號右邊的值不是物件或陣列,就先將其轉為物件

4.函式引數

[[1, 2], [3, 4]].map(([a, b]) => a + b);
// [ 3, 7 ]

預設值

function hello(text="hello world"){}
//等價於
function hello(text){
    text=text||"hello world"
}

undefined就會觸發函式引數的預設值

[1, undefined, 3].map((x = 'yes') => x);
// [ 1, 'yes', 3 ]

5.用途

  • 交換變數的值

    let x = 1;
    let y = 2;
    
    [x, y] = [y, x];
    
  • 從函式返回多個值

    // 返回一個數組
    function example() {
      return [1, 2, 3];
    }
    let [a, b, c] = example();
    
    // 返回一個物件
    function example() {
      return {
        foo: 1,
        bar: 2
      };
    }
    let { foo, bar } = example();
    
  • 函式引數的定義

    // 引數是一組有次序的值
    function f([x, y, z]) { ... }
    f([1, 2, 3]);
    
    // 引數是一組無次序的值
    function f({x, y, z}) { ... }
    f({z: 3, y: 2, x: 1});
    
  • 提取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]
    
  • 遍歷Map結構

    任何部署了Iterator介面的物件,都可以用for...of迴圈遍歷。Map結構原生支援Iterator介面,配合變數的解構賦值,獲取鍵名和鍵值就非常方便。

    var map = new Map();
    map.set('first', 'hello');
    map.set('second', 'world');
    
    for (let [key, value] of map) {
      console.log(key + " is " + value);
    }
    // first is hello
    // second is world
    

    如果只想獲取鍵名,或者只想獲取鍵值

    // 獲取鍵名
    for (let [key] of map) {
      // ...
    }
    
    // 獲取鍵值
    for (let [,value] of map) {
      // ...
    }
    
  • 輸入模組的指定方法

    //載入模組時,往往需要指定輸入哪些方法。解構賦值使得輸入語句非常清晰
    const { SourceMapConsumer, SourceNode } = require("source-map")