變數的解構賦值
阿新 • • 發佈:2019-01-04
解構:按照一定模式,從陣列和物件中提取值,對變數進行賦值。
1.陣列的解構賦值
基本用法
之前的賦值形式為直接指定值,例如let a = 1。ES6允許寫成let [a,b,c] = [1,2,3],從陣列中提取值,按照對應的位置,對變數賦值,只要等號兩邊的模式相同,左邊的變數就會被賦予相應的值。- 如果解構不成功,變數的值就會等於undefined
- 等號左邊的模式只匹配等號右邊的一部分陣列,這是不完全解構,但解構依然成功
- 如果等號右邊不是陣列(不是可遍歷的結構,比如數值、布林值、NaN、undefined、null、{}等),則會報錯
//巢狀陣列解構
let [foo,[[bar],
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,[
a // 1
b // 2
d // 4
// 報錯
let [foo]=1;
let [foo]=false;
let [foo]=NaN;
let [foo]=undefined;
let [foo]=null;
let [foo]={};
let [x, y, z]=newSet(['a','b','c']);
x // "a"
預設值
解構賦值允許指定預設值,但ES6內部使用嚴格相等運算子(===)來判斷一個位置是否有值,即如果變數是嚴格等於undefined,預設值才生效(理解為變數沒有被賦值才需要用到預設值)。//指定預設值
let [foo =true]=[];
foo // true
let [x, y ='b']=['a'];// x='a', y='b'
let [x, y ='b']=['a',undefined];// x='a', y='b'
//預設值不生效
let [x =1]=[undefined];
x // 1
let [x =1]=[null];
x // null,因為null不嚴格等於undefined
function f(){
console.log('aaa');
}
let [x = f()]=[1];//x為1,因為x能夠取到值,函式f不會執行,即變數賦值嚴格等於undefined時,預設值才會生效
let [x =1, y = x]=[];// x=1; y=1
let [x =1, y = x]=[2];// x=2; y=2
let [x =1, y = x]=[1,2];// x=1; y=2
let [x = y, y =1]=[];// ReferenceError,x賦值為undefined,預設值為y,但y沒有宣告,報錯
2.物件的解構賦值
基本用法
與陣列解構賦值不同的是,陣列的元素是按次序排列的,物件的屬性沒有次序,變數必須與屬性同名,才能取到正確的值,物件解構賦值的內部機制是,先找到同名屬性,然後再賦值給對應的變數。let { foo: baz }={ foo:"aaa", bar:"bbb"};
baz // "aaa"
foo // error: foo is not defined
foo是匹配的模式,baz才是變數,被賦值的是變數
let { bar, foo }={ foo:"aaa", bar:"bbb"};
foo // "aaa"
bar // "bbb"
let { baz }={ foo:"aaa", bar:"bbb"};
baz // undefined
let foo;
let {foo}={foo:1};// SyntaxError: Duplicate declaration "foo"
let baz;
let {bar: baz}={bar:1};// SyntaxError: Duplicate declaration "baz"
let foo;
({foo}={foo:1});// 成功
let baz;
({bar: baz}={bar:1});// 成功,圓括號必須有,解析器會將圓括號為首理解成程式碼塊,而不是賦值語句
let obj ={};
let arr =[];
({ foo: obj.prop, bar: arr[0]}={ foo:123, bar:true});
obj // {prop:123}
arr // [true]
預設值
- 物件的解構也可以指定預設值,生效的條件是物件的屬性值嚴格等於undefined
- 如果解構失敗,變數的值等於undefined
- 如果解構模式是巢狀的物件,而且子物件所在的父屬性不存在,會報錯
var{x =3}={};
x // 3
var{x, y =5}={x:1};
x // 1
y // 5
var{x:y =3}={};
y // 3
var{x:y =3}={x:5};
y // 5
var{ message: msg ='Something went wrong'}={};
msg // "Something went wrong"
// 報錯,foo對應子物件,bar是子物件的屬性,foo此時為undefined,取子屬性就會報錯
let {foo: {bar}} = {baz: 'baz'};
相當於let {foo: {bar: bar}} = {baz: 'baz'};
let { log, sin, cos }=Math;
對陣列進行物件解構,arr.length-1對應索引為2,所以值為3
let arr =[1,2,3];
let {0: first,[arr.length -1]: last}= arr;