ES6常用新特性學(xué)習(xí)3-解構(gòu)賦值

1. 簡介

ES6 允許按照一定模式,從數(shù)組和對象中提取值,對變量進(jìn)行賦值,這被稱為解構(gòu)(Destructuring)。它提供了一種更加方便的數(shù)據(jù)訪問方法,對于代碼簡化有很大的作用,也是使用非常頻繁的新特性。

2. 數(shù)組的解構(gòu)賦值

2.1 基本用法

以前,想要提取數(shù)組中的值賦值給相應(yīng)變量,需要每一次進(jìn)行單獨賦值。像下面這樣:

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

現(xiàn)在我們有了更方便的寫法:

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

上面代碼表示,可以從數(shù)組中提取值,按照對應(yīng)位置,對變量賦值。

本質(zhì)上,這種寫法屬于“模式匹配”,只要等號兩邊的模式相同,左邊的變量就會被賦予對應(yīng)的值。

2.2 嵌套解構(gòu)

上面說過,本質(zhì)上,這種寫法屬于“模式匹配”,只要等號兩邊的模式相同,左邊的變量就會被賦予對應(yīng)的值。所以可以使用嵌套數(shù)組進(jìn)行解構(gòu)。

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

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

2.3 對等號右邊值的要求

在進(jìn)行對數(shù)組的解構(gòu)賦值時,等號右邊必須是可遍歷的結(jié)構(gòu),比如說數(shù)組,Set集合,甚至Generator對象。否則會報錯。

字符串在解構(gòu)時會被轉(zhuǎn)化成一個類似數(shù)組的對象,因此可以用于數(shù)組的解構(gòu)賦值

let [a, b, c, d, e] = 'hello';

2.4 不完全解構(gòu)

如果等號左右邊的變量與值的個數(shù)不相等,就會發(fā)生部分解構(gòu)。如:

// 右邊多余的部分會被舍棄
let [a, b] = [1, 2, 3];
console.log(a, b);  // 1 2
// 左邊多余的部分會被賦值為undefined
let [x, y] = [1];
console.log(x, y);  // 1 undefined

2.5 默認(rèn)值

解構(gòu)賦值允許指定默認(rèn)值。當(dāng)左邊的變量解構(gòu)時被賦值為undefined時將使用指定的默認(rèn)值。

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

但是需要注意的是,ES6 內(nèi)部使用嚴(yán)格相等運算符(===),判斷一個位置是否有值。所以,只有當(dāng)一個數(shù)組成員嚴(yán)格等于undefined,默認(rèn)值才會生效。

let [x, y = 'b'] = ['a', null]; // x='a', y=null

因為null不嚴(yán)格等于undefined,所以變量默認(rèn)值不生效,而是被賦值成為了nul。

3. 對象的解構(gòu)賦值

3.1 基本用法

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

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

那么,難道我們解構(gòu)出來的變量必須只能和對象的屬性同名嗎?并不是的,看下面這個例子:

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

其實,解構(gòu)的完整寫法就是如上例所示:

{屬性名:變量名,...}={屬性名:值,...}

真正被賦值的其實是變量名,我們只要保證該變量名的key是和對應(yīng)的需要解構(gòu)的屬性名相同即可。而當(dāng)屬性名與變量名相同時,我們可以簡寫為:

{變量名,...}={屬性名:值,...}

3.2 嵌套解構(gòu)

與數(shù)組一樣,解構(gòu)也可以用于嵌套結(jié)構(gòu)的對象。

let obj = {
  p: [
    'Hello',
    { y: 'World' }
  ]
};

let { p: [x, { y }] } = obj;
x // "Hello"
y // "World"

注意,這時p是模式,不是變量,因此不會被賦值。如果p也要作為變量賦值,可以寫成下面這樣。

let obj = {
  p: [
    'Hello',
    { y: 'World' }
  ]
};

let { p, p: [x, { y }] } = obj;
x // "Hello"
y // "World"
p // ["Hello", {y: "World"}]

下面是一個更復(fù)雜的嵌套解構(gòu):

const node = {
  loc: {
    start: {
      line: 1,
      column: 5
    }
  }
};

let { loc, loc: { start }, loc: { start: { line }} } = node;
line // 1
loc  // Object {start: Object}
start // Object {line: 1, column: 5}

上面代碼有三次解構(gòu)賦值,分別是對loc、start、line三個屬性的解構(gòu)賦值。注意,最后一次對line屬性的解構(gòu)賦值之中,只有l(wèi)ine是變量,loc和start都是模式,不是變量。

其實,從上面兩個例子可以看出,左邊對應(yīng)的模式到了第幾層,解構(gòu)時的賦值就是到第幾層。一切還是那句話,解構(gòu)是模式的匹配。

3.3 對等號右邊值的要求

使用對象解構(gòu)賦值時,右值可以是簡單數(shù)據(jù)類型布爾、字串或者數(shù)字。解構(gòu)時,會先將其轉(zhuǎn)化為對象,再進(jìn)行解構(gòu)。

右值不可以是不能轉(zhuǎn)成對象的null或undefined,因為它們沒有對應(yīng)的包裝類。

3.4 不完全解構(gòu)

如果等號左右邊的變量與值的個數(shù)不相等,就會發(fā)生部分解構(gòu)。如:

// 右邊多余的部分會被舍棄
let {a, b} = {a:1, b:2, c:3};
console.log(a, b);  // 1 2
// 左邊多余的部分會被賦值為undefined
let {c, d} = {c:1};
console.log(c, d);  // 1 undefined

3.5 默認(rèn)值

let {a, b =2 } = {a:1};
console.log(a, b);  // 1 2

同樣需要注意,只有賦值以后嚴(yán)格等于undefined時,默認(rèn)值才會生效。

4. 用途

變量的解構(gòu)賦值用途很多。

  1. 交換變量的值
let x = 1;
let y = 2;

[x, y] = [y, x];

上面代碼交換變量x和y的值,這樣的寫法不僅簡潔,而且易讀,語義非常清晰。

  1. 從函數(shù)返回多個值

函數(shù)只能返回一個值,如果要返回多個值,只能將它們放在數(shù)組或?qū)ο罄锓祷?。有了解?gòu)賦值,取出這些值就非常方便。

// 返回一個數(shù)組

function example() {
  return [1, 2, 3];
}
let [a, b, c] = example();

// 返回一個對象

function example() {
  return {
    foo: 1,
    bar: 2
  };
}
let { foo, bar } = example();
  1. 函數(shù)參數(shù)的定義

解構(gòu)賦值可以方便地將一組參數(shù)與變量名對應(yīng)起來。

// 參數(shù)是一組有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);

// 參數(shù)是一組無次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});
  1. 提取 JSON 數(shù)據(jù)

解構(gòu)賦值對提取 JSON 對象中的數(shù)據(jù),尤其有用。

let jsonData = {
  id: 42,
  status: "OK",
  data: [867, 5309]
};

let { id, status, data: number } = jsonData;

console.log(id, status, number);
// 42, "OK", [867, 5309]

上面代碼可以快速提取 JSON 數(shù)據(jù)的值。

  1. 函數(shù)參數(shù)的默認(rèn)值
jQuery.ajax = function (url, {
  async = true,
  beforeSend = function () {},
  cache = true,
  complete = function () {},
  crossDomain = false,
  global = true,
  // ... more config
}) {
  // ... do stuff
};

指定參數(shù)的默認(rèn)值,就避免了在函數(shù)體內(nèi)部再寫var foo = config.foo || 'default foo';這樣的語句。

  1. 遍歷 Map 結(jié)構(gòu)

任何部署了 Iterator 接口的對象,都可以用for...of循環(huán)遍歷。Map 結(jié)構(gòu)原生支持 Iterator 接口,配合變量的解構(gòu)賦值,獲取鍵名和鍵值就非常方便。

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

(7)輸入模塊的指定方法

加載模塊時,往往需要指定輸入哪些方法。解構(gòu)賦值使得輸入語句非常清晰。

const { SourceMapConsumer, SourceNode } = require("source-map");

參考

變量的解構(gòu)賦值
深入ES6 三 解構(gòu)賦值
ES6這些就夠了

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 今天用網(wǎng)易云聽歌,聽到鄧麗君阿姨的歌,順便知乎了一下,看到知乎上推薦鄧麗君阿姨的《梅花》,我也去聽了,一開口我有點...
    __也要楚天闊閱讀 161評論 0 0
  • 也許在旁人看來,過于冷清。 畢竟一個年華二八的女子,獨自一人沒有男朋友,而且還獨居,是件多么可怕的事情。 偶爾是會...
    Jane零閱讀 473評論 2 2
  • 昨晚培訓(xùn)內(nèi)容: 1. 系統(tǒng)分析法,任何事或物都可以找出其相關(guān)聯(lián)的組織或環(huán)境,首先是明確主體,其次找出結(jié)構(gòu)或?qū)哟侮P(guān)系...
    呂姜瑤閱讀 310評論 0 0
  • 一抹瑰麗的朝霞,像溶化的水彩,令人神怡地在天空中朦朧地滲開。 ------------------ The end...
    荷語微光閱讀 307評論 0 0

友情鏈接更多精彩內(nèi)容