[記錄] ECMAScript 6 - 解構(gòu)賦值


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


ES6 允許按照一定模式,從數(shù)組和對(duì)象中提取值,對(duì)變量進(jìn)行賦值,這被稱為解構(gòu)。

最近在學(xué)習(xí)vuex中actions的參數(shù)中使用到了對(duì)象的解構(gòu)賦值,故此前來學(xué)習(xí)了解 解構(gòu)賦值語法

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

    let a = 1; let b = 2; let c = 3;
    ES6可以寫成下面這樣為變量賦值。
    let [a,b,c] = [1,2,3];

    有關(guān)模式匹配的規(guī)則:

    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 // []

關(guān)于解構(gòu)賦值參數(shù)不完整的情況:

let [foo] = [];
let [bar, foo] = [1];

解構(gòu)不成功的情況下,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

上面兩個(gè)栗子,都屬于不完全解構(gòu),但都可以成功。

如果等號(hào)的右邊不是可遍歷的結(jié)構(gòu)(數(shù)組,Set)那么將會(huì)報(bào)錯(cuò)。

// 編譯報(bào)錯(cuò)
let[foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};

對(duì)于Set結(jié)構(gòu)進(jìn)行解構(gòu)賦值。

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

** 解構(gòu)賦值 - 默認(rèn)值 **

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 內(nèi)部使用嚴(yán)格相等運(yùn)算符(===),判斷一個(gè)位置是否有值。如果一個(gè)數(shù)組成員不嚴(yán)格等于undefined,默認(rèn)值是不會(huì)生效的。*

let [x = 1] = [ undefined ];記得加上中括號(hào),否則報(bào)錯(cuò)
x // 1
let[ x = 1 ] = [ null ];
x // null

上面代碼中,如果一個(gè)數(shù)組成員是null,默認(rèn)值就不會(huì)生效,因?yàn)閚ull不嚴(yán)格等于undefined。

** 對(duì)象的解構(gòu)賦值 **
解構(gòu)不僅可以用于數(shù)組,還可以用于對(duì)象。

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

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

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

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'

這實(shí)際說明了對(duì)象的解構(gòu)賦值是下面形式的簡(jiǎn)寫。

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

也就是說,對(duì)象的解構(gòu)賦值的內(nèi)部機(jī)制,是先找到同名屬性,然后再賦給對(duì)應(yīng)的變量。真正被賦值的是后者,而不是前者。

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

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

** 解構(gòu)失敗 **
默認(rèn)值生效的條件是,對(duì)象的屬性值嚴(yán)格等于undefined。

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

解構(gòu)失敗變量的值等于undefined。

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

如果解構(gòu)模式是嵌套的對(duì)象,而且子對(duì)象所在的父屬性不存在,那么將會(huì)報(bào)錯(cuò)。

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

對(duì)象的解構(gòu)賦值,可以很方便地將現(xiàn)有對(duì)象的方法,賦值到某個(gè)變量。

let { log, sin, cos } = Math;

上面代碼將Math對(duì)象的對(duì)數(shù)、正弦、余弦三個(gè)方法,賦值到對(duì)應(yīng)的變量上,使用起來就會(huì)方便很多。

由于數(shù)組本質(zhì)是特殊的對(duì)象,因此可以對(duì)數(shù)組進(jìn)行對(duì)象屬性的解構(gòu)。

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

上面代碼對(duì)數(shù)組進(jìn)行對(duì)象解構(gòu)。數(shù)組arr的0鍵對(duì)應(yīng)的值是1,[arr.length - 1]就是2鍵,對(duì)應(yīng)的值是3。方括號(hào)這種寫法,屬于“屬性名表達(dá)式”

** 字符串的解構(gòu)賦值 **
字符串能被轉(zhuǎn)換成一個(gè)類似數(shù)組的對(duì)象,因此字符串也可以解構(gòu)賦值

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

類似數(shù)組的對(duì)象都有一個(gè)length屬性,因此還可以對(duì)這個(gè)屬性解構(gòu)賦值。

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

** 數(shù)值和布爾值的解構(gòu)賦值 **
解構(gòu)賦值時(shí),如果等號(hào)右邊是數(shù)值和布爾值,則會(huì)先轉(zhuǎn)為對(duì)象。

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

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

解構(gòu)賦值的規(guī)則是,只要等號(hào)右邊的值不是對(duì)象或數(shù)組,就先將其轉(zhuǎn)為對(duì)象。由于undefined和null無法轉(zhuǎn)為對(duì)象,所以對(duì)它們進(jìn)行解構(gòu)賦值,都會(huì)報(bào)錯(cuò)。

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

** 函數(shù)參數(shù)的解構(gòu)賦值 **
函數(shù)的參數(shù)也可以使用解構(gòu)賦值。

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

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

上面代碼中,函數(shù)add的參數(shù)表面上是一個(gè)數(shù)組,但在傳入?yún)?shù)的那一刻,數(shù)組參數(shù)就被解構(gòu)成變量x和y。對(duì)于函數(shù)內(nèi)部的代碼來說,它們能感受到的參數(shù)就是x和y。

下面是另一個(gè)例子。

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

函數(shù)參數(shù)的解構(gòu)也可以使用默認(rèn)值。

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]

上面代碼中,函數(shù)move的參數(shù)是一個(gè)對(duì)象,通過對(duì)這個(gè)對(duì)象進(jìn)行解構(gòu),得到變量x和y的值。如果解構(gòu)失敗,x和y等于默認(rèn)值。

注意,下面的寫法會(huì)得到不一樣的結(jié)果。

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]

上面代碼是為函數(shù)move的參數(shù)指定默認(rèn)值,而不是為變量x和y指定默認(rèn)值,所以會(huì)得到與前一種寫法不同的結(jié)果。

undefined就會(huì)觸發(fā)函數(shù)參數(shù)的默認(rèn)值。

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


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

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

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

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