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 [x, y] = [1, 2, 3]; x // 1 y // 2 let [a, [b], d] = [1, [2, 3], 4]; a // 1 b // 2 d // 4
若是等號的右邊不是數組(嚴格地說,不是可遍歷的結構),那麼將會報錯。
解構賦值容許指定默認值。函數
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, y = x] = []; // x=1; y=1 let [x = y, y = 1] = []; // ReferenceError: y is not defined
ES6 內部使用嚴格相等運算符(===),判斷一個位置是否有值
若是默認值是一個表達式,那麼這個表達式是惰性求值的,即只有在用到的時候,纔會求值。prototype
function f() { console.log('aaa'); } let [x = f()] = [1]; ///由於x能取到值,因此函數f根本不會執行
對象的解構與數組有一個重要的不一樣。數組的元素是按次序排列的,變量的取值由它的位置決定;而對象的屬性沒有次序,變量必須與屬性同名,才能取到正確的值。code
let { bar, foo } = { foo: "aaa", bar: "bbb" }; foo // "aaa" bar // "bbb" let { baz } = { foo: "aaa", bar: "bbb" }; baz // undefined //若是變量名與屬性名不一致,必須寫成下面這樣 let obj = { first: 'hello', last: 'world' }; let { first: f, last: l } = obj; f // 'hello' l // 'world' first // undefined
若是要將一個已經聲明的變量用於解構賦值,必須很是當心。對象
// 錯誤的寫法 let x; {x} = {x: 1}; // SyntaxError: syntax error // 正確的寫法 let x; ({x} = {x: 1});
因爲數組本質是特殊的對象,所以能夠對數組進行對象屬性的解構。繼承
let arr = [1, 2, 3]; let {0 : first, [arr.length - 1] : last} = arr; first // 1 last // 3
因爲解構賦值要求等號右邊是一個對象,因此若是等號右邊是undefined或null,就會報錯,由於它們沒法轉爲對象。
let { x, y, ...z } = null; // 運行時錯誤 let { x, y, ...z } = undefined; // 運行時錯誤
解構賦值必須是最後一個參數,不然會報錯。
let { ...x, y, z } = obj; // 句法錯誤 let { x, ...y, ...z } = obj; // 句法錯誤
解構賦值的拷貝是淺拷貝,即若是一個鍵的值是複合類型的值(數組、對象、函數),那麼解構賦值拷貝的是這個值的引用,而不是這個值的副本。
let obj = { a: { b: 1 } }; let { ...x } = obj; obj.a.b = 2; x.a.b // 2
擴展運算符的解構賦值,不能複製繼承自原型對象的屬性。
let o1 = { a: 1 }; let o2 = { b: 2 }; o2.__proto__ = o1; let { ...o3 } = o2; o3 // { b: 2 } o3.a // undefined
若是使用解構賦值,擴展運算符後面必須是一個變量名,而不能是一個解構賦值表達式。
let { x, ...{ y, z } } = o; // SyntaxError
字符串也能夠解構賦值。這是由於此時,字符串被轉換成了一個相似數組的對象。字符串
const [a, b, c, d, e] = 'hello'; a // "h" b // "e" c // "l" d // "l" e // "o" let {length : len} = 'hello'; len // 5
解構賦值的規則是,只要等號右邊的值不是對象或數組,就先將其轉爲對象。原型
let {toString: s} = 123; s === Number.prototype.toString // true let {toString: s} = true; s === Boolean.prototype.toString // true
function add([x, y]){ return x + y; } add([1, 2]); // 3
函數add的參數表面上是一個數組,但在傳入參數的那一刻,數組參數就被解構成變量x和y。io
//默認值 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]