ES6 允許按照一定模式,從數組和對象中提取值,對變量進行賦值,這被稱爲解構(Destructuring)。
一.對象的解構賦值
1.基本寫法
-
基本寫法
let { foo, bar } = { foo: 'aaa', bar: 'bbb' }; foo // "aaa" bar // "bbb"
2.特點
-
① 對象屬性賦值是按照屬性名匹配的,和屬性順序無關。
let { bar, foo } = { foo: 'aaa', bar: 'bbb' }; foo // "aaa" bar // "bbb"
-
② 對象解構無相應屬性,賦值爲
undefined
let {foo} = {bar: 'baz'}; foo // undefined
-
③ 對象的解構賦值可以取到繼承的屬性
const obj1 = {}; const obj2 = { foo: 'bar' }; Object.setPrototypeOf(obj1, obj2); const { foo } = obj1; foo // "bar"
-
④ 與數組一樣,解構也可以用於嵌套結構的對象。
//一.嵌套結構 let obj = { p: [ 'Hello', { y: 'World' } ] }; let { p: [x, { y }] } = obj; x // "Hello" y // "World" //二.這時p是模式,不是變量,因此不會被賦值。如果p也要作爲變量賦值,可以寫成下面這樣 let obj = { p: [ 'Hello', { y: 'World' } ] }; let { p, p: [x, { y }] } = obj; x // "Hello" y // "World" p // ["Hello", {y: "World"}] //三.關於嵌套解構更多範例: //下面代碼有三次解構賦值,分別是對loc、start、line三個屬性的解構賦值。注意,最後一次對line屬性的解構賦值之中,只有line是變量,loc和start都是模式,不是變量。 const node = { loc: { start: { line: 1, column: 5 } } }; let { loc, loc: { start }, loc: { start: { line }} } = node; line // 1 loc // Object {start: Object} start // Object {line: 1, column: 5} //嵌套賦值的例子 let obj = {}; let arr = []; ({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true }); obj // {prop:123} arr // [true] // 報錯 //下面代碼中,等號左邊對象的foo屬性,對應一個子對象。該子對象的bar屬性,解構時會報錯。原因很簡單,因爲foo這時等於undefined,再取子屬性就會報錯。 let {foo: {bar}} = {baz: 'baz'};
3.對象解構賦值的本質
-
對象的解構賦值的內部機制,是先找到同名屬性,然後再賦給對應的變量。真正被賦值的是後者,而不是前者。
//變量名與屬性名處理 let { foo: baz } = { foo: 'aaa', bar: 'bbb' }; baz // "aaa" let obj = { first: 'hello', last: 'world' }; let { first: f, last: l } = obj; f // 'hello' l // 'world' //如下:foo是匹配的模式,baz纔是變量。真正被賦值的是變量baz,而不是模式foo。 let { foo: baz } = { foo: 'aaa', bar: 'bbb' }; baz // "aaa" foo // error: foo is not defined
4.對象解構賦值的使用
-
① 將現有變量賦值給我們定義的同名變量。
// 例一 將Math對象的對數、正弦、餘弦三個方法,賦值到對應的變量上 let { log, sin, cos } = Math; // 例二 console.log賦值到log變量 const { log } = console; log('hello') // hello
5.默認值
-
對象的解構也可以指定默認值。
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"
-
默認值生效的條件是,對象的屬性值嚴格等於undefined。
var {x = 3} = {x: undefined}; x // 3 var {x = 3} = {x: null}; x // null
6.解決歧義
-
如果要將一個已經聲明的變量用於解構賦值,可能會出現歧義。
// 一 錯誤的寫法:因爲 JavaScript 引擎會將{x}理解成一個代碼塊,從而發生語法錯誤。 let x; {x} = {x: 1}; // SyntaxError: syntax error //二 將對象放在一個圓括號裏面,解釋爲對象 // 正確的寫法 let x; ({x} = {x: 1});
-
解構賦值允許等號左邊的模式之中,不放置任何變量名。因此,可以寫出非常古怪的賦值表達式。
({} = [true, false]); ({} = 'abc'); ({} = []);
-
由於數組本質是特殊的對象,因此可以對數組進行對象屬性的解構。
let arr = [1, 2, 3]; let {0 : first, [arr.length - 1] : last} = arr; first // 1 last // 3