[記錄] ECMAScript 6 - 解構賦值


title: ECMAScript 6 - 解構賦值
date: 2017年7月31日 12:18:15
tags: js
categories: 教程
author: "JiaWei"


ES6 允許按照一定模式,從數組和對象中提取值,對變量進行賦值,這被稱為解構。

最近在學習vuex中actions的參數中使用到了對象的解構賦值,故此前來學習了解 解構賦值語法

  1. 開始
    以前,為變量賦值,只能直接指定值。

    let a = 1; let b = 2; let c = 3;
    ES6可以寫成下面這樣為變量賦值。
    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] = [];
let [bar, foo] = [1];

解構不成功的情況下,foo的值等于undefined

let [x,y] = [1,2,3];
x // 1 ,y // 2
let [a,[b],d] = [a,[2,3],4];
a // 1 , b //2 ,d // 4

上面兩個栗子,都屬于不完全解構,但都可以成功。

如果等號的右邊不是可遍歷的結構(數組,Set)那么將會報錯。

// 編譯報錯
let[foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};

對于Set結構進行解構賦值。

let [x,y,z] = new Set([1,2,3]);
x // 1

** 解構賦值 - 默認值 **

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

  • ES6 內部使用嚴格相等運算符(===),判斷一個位置是否有值。如果一個數組成員不嚴格等于undefined,默認值是不會生效的。*

let [x = 1] = [ undefined ];記得加上中括號,否則報錯
x // 1
let[ x = 1 ] = [ null ];
x // null

上面代碼中,如果一個數組成員是null,默認值就不會生效,因為null不嚴格等于undefined。

** 對象的解構賦值 **
解構不僅可以用于數組,還可以用于對象。

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

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

如果變量名與屬性名不一致,必須寫成下面這樣。

var { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"
let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f // 'hello'
l // 'world'

這實際說明了對象的解構賦值是下面形式的簡寫。

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

也就是說,對象的解構賦值的內部機制,是先找到同名屬性,然后再賦給對應的變量。真正被賦值的是后者,而不是前者。

let { foo: baz } = { foo: "aaa", bar: "bbb" };
baz // "aaa"
foo // error: foo is not defined

上面代碼中,foo是匹配的模式,baz才是變量。真正被賦值的是變量baz,而不是模式foo。

** 解構失敗 **
默認值生效的條件是,對象的屬性值嚴格等于undefined。

var {x = 3} = {x: undefined};
x // 3
var {x = 3} = {x: null};
x // null

解構失敗變量的值等于undefined

let { foo } = { bar : 'baz' };
foo // undefined

如果解構模式是嵌套的對象,而且子對象所在的父屬性不存在,那么將會報錯。

let {foo: {bar}} = {baz: 'baz'};

對象的解構賦值,可以很方便地將現有對象的方法,賦值到某個變量。

let { log, sin, cos } = Math;

上面代碼將Math對象的對數、正弦、余弦三個方法,賦值到對應的變量上,使用起來就會方便很多。

由于數組本質是特殊的對象,因此可以對數組進行對象屬性的解構。

let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1 , last // 3

上面代碼對數組進行對象解構。數組arr的0鍵對應的值是1,[arr.length - 1]就是2鍵,對應的值是3。方括號這種寫法,屬于“屬性名表達式”

** 字符串的解構賦值 **
字符串能被轉換成一個類似數組的對象,因此字符串也可以解構賦值

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

類似數組的對象都有一個length屬性,因此還可以對這個屬性解構賦值。

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

** 數值和布爾值的解構賦值 **
解構賦值時,如果等號右邊是數值和布爾值,則會先轉為對象。

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

上面代碼中,數值和布爾值的包裝對象都有toString屬性,因此變量s都能取到值。

解構賦值的規則是,只要等號右邊的值不是對象或數組,就先將其轉為對象。由于undefined和null無法轉為對象,所以對它們進行解構賦值,都會報錯。

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

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

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

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

上面代碼中,函數add的參數表面上是一個數組,但在傳入參數的那一刻,數組參數就被解構成變量x和y。對于函數內部的代碼來說,它們能感受到的參數就是x和y。

下面是另一個例子。

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

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

function move({x = 0, y = 0} = {}) {
return [x, y];
}

move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]

上面代碼中,函數move的參數是一個對象,通過對這個對象進行解構,得到變量x和y的值。如果解構失敗,x和y等于默認值。

注意,下面的寫法會得到不一樣的結果。

function move({x, y} = { x: 0, y: 0 }) {
return [x, y];
}

move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]

上面代碼是為函數move的參數指定默認值,而不是為變量x和y指定默認值,所以會得到與前一種寫法不同的結果。

undefined就會觸發函數參數的默認值。

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


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1.數組的解構賦值 2.對象的解構賦值 3.字符串的解構賦值 4.數值和布爾值的解構賦值 5.函數參數的解構賦值 ...
    卞卞村長L閱讀 922評論 0 0
  • 基本用法 ES6 允許按照一定模式,從數組和對象中提取值,對變量進行賦值,這被稱為解構(Destructuring...
    嘉奇呦_nice閱讀 791評論 0 2
  • 數組的解構賦值 基本用法 ES6允許按照一定模式,從數組和對象中提取值,對變量進行賦值,這被稱為解構(Destru...
    呼呼哥閱讀 435評論 0 3
  • 本人是android開發的,由于最近React Native的火熱,再加上自己完全不懂JS的語法,俗話說的好"落后...
    Bui_vlee閱讀 403評論 0 0
  • 當一個人難過到極致 除了眼淚 TA拿不出任何東西與世界對抗 反正一個人在家 眼睛腫了也不會被人發現 字打錯了可以改...
    易達閱讀 144評論 0 0