ES6筆記(3)-- 解構賦值


系列文章 -- ES6筆記系列

 

解構賦值,即對某種結構進行解析,然后將解析出來的值賦值給相關的變量,常見的有數組、對象、字符串的解構賦值等

一、數組的解構賦值

function ids() {
    return [1, 2, 3];
}
 
var [id1, id2, id3] = ids();

console.log(id1, id2, id3); // 1 2 3

如上,解析返回的數組,取出值並賦給相應的變量,這就是解構賦值

1. 還可以嵌套多層,只要相應的模式匹配了就能解析出來

var [a, [b, [c]]] = [1, [2, [3]]];

a // 1
b // 2
c // 3

2. 如若模式不匹配則報錯

var [a, [b, [c]]] = [1, [2, 3]]; // Uncaught TypeError: undefined is not a function

a 

其實,解構賦值內部的實現方式使用到了ES6的Iterator迭代器,通過層層遍歷,保證了相應值的獲取

3. 解構不成功,但模式匹配了,相應值為undefined

var [a, b] = [1];

a // 1
b // undefined

4. 不需要匹配的位置可以置空

var [, b] = [1, 2];

b // 2

5. 使用...這個擴展運算符,匹配余下的所以值,形成一個數組(匹配不上則為[]),這個符號內部也用到了迭代器Iterator

var [a, ...b] = [1, 2, 3];

a // 1
b // [2, 3]


var [a, ...b] = [1];

a // 1
b // []

6. 可以設置默認值,當相應的值嚴格等於undefined時,默認值會生效

var [a, b = [2, 3]] = [1];

a // 1
b // [2, 3]
var [a, b = [2, 3]] = [1, undefined];

a // 1
b // [2, 3]
var [a, b = [2, 3]] = [1, null];

a // 1
b // null

7. 惰性求值,對於默認值中出現函數調用模式的,只有默認值生效,函數才會調用,如下,foo函數將不會被調用

function foo() {
    console.log('hit');
}

var [str = foo()] = [1];

str // 1

8. 可以方便的進行變量值的交換

var x = 1,
    y = 2;
   
[x, y] = [y, x];

x // 2
y // 1

 

二、對象的解構賦值

與數組類似,對象也可以進行解構賦值

var {name, agee} = {
    name: 'jack',
    age: 22,
}; name // jack agee // undefined

如上,對象的解構賦值要求屬性名稱匹配正確,agee不匹配則變成undefined

1. 不過我們可以自定義屬性名稱,但要注意的是被賦值的只是我們自定義的屬性名稱,匹配的模式(項)並未被賦值

var {name, id: ID} = {
    name: 'jack',
    id: 1
};

ID // 1
id // Uncaught ReferenceError: id is not defined

更復雜的如

var {
    a0: {
        b0: {
            c0
        }
    }
} = {
    a0: {
        b0: {
            c0: 'cc',
            d0: 'dd'
        }
    }
};

a0 // Uncaught ReferenceError: a0 is not defined
b0 // Uncaught ReferenceError: b0 is not defined
c0 // cc

2. 類似於數組,也可使用默認值

var {a:b = 2} = {};
b // 2


var {a:b = 2} = {
    a: 1
};
b // 1

3. 因為數組實際上也是個對象,所以

var {0: one, 1: two} = [1, 2];

two // 2

4. 可以方便地將某個對象上的屬性方法一次性提取出來

var {map, slice} = Array.prototype;

slice //
const {foo, bar} = require('./util');

5. 非聲明時的解構賦值

非聲明時,這里是指純粹的解構賦值,如下代碼

var a;
{a} = {
    a: 1
}; // Uncaught SyntaxError: Unexpected token =

a 

以上代碼報錯了,但某些情況下我們還是需要直接賦值怎么辦?

大括號{位於行首,匹配了}之后JS引擎就會認為{a}是一個代碼塊,所以等號就出問題了,解決方式是在行首放個括號(,即外包裹一層括號()

var a;
({a} = {
    a: 1
}); 

a // 1

括號的出現,讓整個解構賦值的結構被看做一個代碼塊,而內部的{a}模式則可以正常匹配到

細心的盆友會注意到,右括號換個位置,報錯了

var a;
({a}) = {
    a: 1
}; // Uncaught SyntaxError: Unexpected token (

a 

6. 其實,解構賦值中括號的使用還是有講究的

1) 不能使用括號的情況

 1-1)變量聲明語句中,不能帶有括號

// 以下代碼都會報錯

var [(a)] = [1];

var {x: (c)} = {};
var ({x: c}) = {};
var {(x: c)} = {};
var {(x): c} = {};

var { o: ({ p: p }) } = { o: { p: 2 } };

 1-2)函數參數中,模式不能帶有括號

// 報錯
function f([(z)]) { 
    return z;
}

f([1])

 1-3)賦值語句中,不能將整個模式,或嵌套模式中的一層,放在括號之中

var a;
({a}) = {
    a: 1
}; // Uncaught SyntaxError: Unexpected token (

a 

2)可以使用括號的情況

可以使用括號的情況很好記,只有一種:賦值語句的非模式部分,可以使用括號

// 都正確
[(b)] = [3]; 
({ p: (d) } = {}); 
[(b)] = ([3]); 

 

三、字符串的解構賦值

字符串也可進行解構賦值,因為此時的字符串被轉換成了類數組的對象,模式能夠匹配起來,如

var [a, b] = 'str';
a // s
b // t


var {0:a, 1:b, length:len} = 'str';
a // s
b // t
len // 3

四、其他類型的解構賦值

1. 解構賦值的規則是,只要等號右邊的值不是對象,就先嘗試將其轉為對象。如果轉換之后的對象或原對象擁有Iterator接口,則可以進行解構賦值,否則會報錯。

var {toString: s} = 1;
s //


var {toString: s} = true;
s //

以上的數組和布爾值會轉換成對象,toString模式匹配上了對象的toString屬性,所以解構成功,而null或undefined卻不能轉換成此類對象,所以報錯

var {toString: s} = null;
s // Uncaught TypeError: Cannot match against 'undefined' or 'null'.

ES6引入了Iterator迭代器,集合Set或Generator生成器函數等都部署了這個Iterator接口,所以也可以用來進行解構賦值

2. 比如Set的解構賦值

var [a, b, c] = new Set([1, 2, 3]);

a // 1
b // 2
c // 3

3. 函數參數的解構賦值

function calc([a, b, c = 10]) {
    console.log(a + b + c); // 13
}

calc([1, 2]);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM