ES6系列之變量的解構賦值

1.什麼是解構?

ES6容許按照必定模式,從數組和對象中提取值,對變量進行賦值,這被稱爲解構。它在語法上比ES5所提供的更加簡潔、緊湊、清晰。它不只能減小你的代碼量,還能從根本上改變你的編碼方式。javascript

2.數組解構

之前,爲變量賦值,咱們只能直接指定值,好比java

let a = 1;
let b = 2; 
let c = 3;

如今能夠用數組解構的方式來進行賦值json

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

這是數組解構最基本類型的用法,還能夠解構對象數組數組

// 對象數組解構
let [a, b, c] = [{name: 'jacky'}, {name: 'monkey'}, {name: 'houge'}];
console.log(a, b, c); // {name: 'jacky'}, {name: 'monkey'}, {name: 'houge'}

3.數組模式和賦值模式統一

這條能夠理解爲等號左邊和等號右邊的形式要統一,若是不統一解構將失敗。函數

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

 // 提取除第2、三個外的全部數值
let [a, , , d] = [1, 2, 3, 4];
console.log(a, d); //1 4
    
let [a, ...b] = [1, 2, 3, 4];
console.log(a, b); // 1 [2, 3, 4]
        
let [a, , , ...d] = [1, 2, 3, 4, 5];
console.log(a, d); // 1 [4, 5]

若是解構不成功,變量的值就等於undefined編碼

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

let [c] = [];
console.log(c); // undefined

上述是徹底解構的狀況,還有一種是不徹底解構,即等號左邊的模式,只匹配一部分的等號右邊的數組,解構依然能夠成功。prototype

let [x, y] = [1, 2, 3]; 
console.log(x, y); // 1 2

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

4.解構的默認值

解構賦值容許指定默認值。code

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

let [a=1, b=2, c, d=13] = [10, 11, 12];
console.log(a, b, c, d); // 10 11 12 13

5.對象的解構賦值

對象的解構與數組有一個重要的不一樣。數組的元素是按次序排列的,變量的取值由它的位置決定;而對象的屬性沒有次序,變量必須與屬性同名,才能取到正確的值。對象

// 對象解構賦值的內部機制,是先找到同名屬性,而後再賦給對應的變量。真正被賦值的是後者,而非前者。
let obj = { a: "aaa", b: "bbb" };
let { a: x, b: y } = obj; 
console.log(x, y); // aaa bbb

let { a, b } = { a: 'aaa', b: 'bbb' };
console.log(a, b); // aaa bbb

// 不按照順序
let { b, a } = { a: 'test1', b: 'test2' }
console.log(a, b) // test1 test2


// 嵌套解構
let { obj: { name }} = { obj: { name: 'jacky', age: '22' } }
console.log(name) // jacky

// 稍微複雜的嵌套
let obj = {
    p: [
        'Hello',
        { y: 'World' }
    ]
};

let { p: [x, { y }] } = obj;
console.log(x, y); // Hello World

若是變量名與屬性名不一致,必須寫成下面這樣。token

var { foo: rename } = { foo: "aaa",bar: "bbb" };
console.log(rename); // aaa
console.log(foo); // Uncaught ReferenceError: foo is not defined

若是在解構以前就定義了變量,這時候再解構會出現問題。下面是錯誤的代碼,編譯會報錯(由於js引擎會將{a}理解成一個代碼塊,從而發生語法錯誤。只有不將大括號寫在行首,避免js將其解釋成代碼塊,才能解決這個問題)

let a;
let obj = { a: "aaa" };
{a} = obj; // Uncaught SyntaxError: Unexpected token '='

要解決報錯,使程序正常,這時候只要在解構的語句外邊加一個圓括號就能夠了

let a;
let obj = { a: "aaa" };
( {a} = obj );
console.log(a); // aaa

6.函數參數

函數的參數也可使用解構賦值。

function add([x, y]){
  return x + y;
}

add([1, 2]); // 3

函數參數的解構也可使用默認值。

function fn(x, y = 7) {
    return x + y;
}
console.log(fn(3)); // 10

7.字符串解構

字符串被轉換成了一個相似數組的對象。

const [a, b, c, d, e, f] = "hello";
console.log(a); //h
console.log(b); //e
console.log(c); //l
console.log(d); //l
console.log(e); //o
console.log(f); //undefined

8.數值和布爾值的解構賦值

解構賦值時,若是等號右邊是數值和布爾值,則會先轉爲對象。

let {toString: s} = 0;
console.log(s === Number.prototype.toString); // true

let {toString: s} = true;
console.log(s === Boolean.prototype.toString); // true

解構賦值的規則是,只要等號右邊的值不是對象或數組,就先將其轉爲對象。因爲undefinednull沒法轉爲對象,因此對它們進行解構賦值,都會報錯。

let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError

9.解構賦值的應用

1.交換變量的值

一般交換兩個變量的方法須要一個額外的臨時變量,以下

let a = 1;
let b = 2;
let temp;

temp = a;
a = b;
b = temp;

console.log(a, b); // 2 1

用ES6解構賦值的話,會變得很簡潔

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

console.log(a, b); // 2 1

2.從函數返回多個值

函數只能返回一個值,若是要返回多個值,只能將它們放在數組或對象裏返回。有了解構賦值,取出這些值就很是方便。

// 返回一個數組
function example() {
  return [1, 2, 3];
}
let [a, b, c] = example();

// 返回一個對象
function example() {
  return {
    foo: 1,
    bar: 2
  };
}
let { foo, bar } = example();

3.訪問數組中元素

有種場景,好比有一個數組(可能爲空)。而且但願訪問數組的第一個、第二個或第n個項,但若是該項不存在,則使用指定默認值。
一般會使用數組的length屬性來判斷

const list = [];

let firstItem = 'hello';
if (list.length > 0) {
    firstItem = list[0];
}

console.log(firstItem); // hello

若是用ES6解構賦值來實現上述邏輯

const list = [];
const [firstItem = 'hello'] = list;

console.log(firstItem); // 'hello'

4.提取 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]

5.遍歷 Map 結構

任何部署了 Iterator 接口的對象,均可以用for...of循環遍歷。Map 結構原生支持 Iterator 接口,配合變量的解構賦值,獲取鍵名和鍵值就很是方便。

const 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) {
  // ...
}

文章部份內容參考:阮一峯老師的《ECMAScript 6 入門》一書

相關文章
相關標籤/搜索