談談神祕的ES6——(五)解構賦值【對象篇】

上一節課咱們瞭解了有關數組的解構賦值相關內容,這節課,咱們接着,來說講對象的解構賦值。javascript

解構不只能夠用於數組,還能夠用於對象。java

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

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

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

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

上面代碼的第一個例子,等號左邊的兩個變量的次序,與等號右邊兩個同名屬性的次序不一致,可是對取值徹底沒有影響。第二個例子的變量沒有對應的同名屬性,致使取不到值,最後等於undefined。數組

若是變量名與屬性名不一致,必須寫成下面這樣。微信

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'

這實際上說明,對象的解構賦值是下面形式的簡寫學習

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

也就是說,對象的解構賦值的內部機制,是先找到同名屬性,而後再賦給對應的變量。真正被賦值的是後者,而不是前者。code

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

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

與數組同樣,解構也能夠用於嵌套結構的對象。對象

let obj = {
  p: [
    'Hello',
    { y: 'World' }
  ]
};

let { p: [x, { y }] } = obj;
x // "Hello"
y // "World"

注意,這時p是模式,不是變量,所以不會被賦值。若是p也要做爲變量賦值,能夠寫成下面這樣。ip

let obj = {
  p: [
    'Hello',
    { y: 'World' }
  ]
};

let { p, p: [x, { y }] } = obj;
x // "Hello"
y // "World"
p // ["Hello", {y: "World"}]

下面是另外一個例子。

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}

上面代碼有三次解構賦值,分別是對locstartline三個屬性的解構賦值。注意,最後一次對line屬性的解構賦值之中,只有line是變量,locstart都是模式,不是變量。

下面是嵌套賦值的例子。

let obj = {};
let arr = [];

({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true });

obj // {prop:123}
arr // [true]

對象的解構也能夠指定默認值。

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

上面代碼中,屬性x等於null,由於nullundefined不嚴格相等,因此是個有效的賦值,致使默認值3不會生效。

若是解構失敗,變量的值等於undefined

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

若是解構模式是嵌套的對象,並且子對象所在的父屬性不存在,那麼將會報錯。

// 報錯
let {foo: {bar}} = {baz: 'baz'};

上面代碼中,等號左邊對象的foo屬性,對應一個子對象。該子對象的bar屬性,解構時會報錯。緣由很簡單,由於foo這時等於undefined,再取子屬性就會報錯,請看下面的代碼。

let _tmp = {baz: 'baz'};
_tmp.foo.bar // 報錯

若是要將一個已經聲明的變量用於解構賦值,必須很是當心。

// 錯誤的寫法
let x;
{x} = {x: 1};
// SyntaxError: syntax error

上面代碼的寫法會報錯,由於 JavaScript 引擎會將{x}理解成一個代碼塊,從而發生語法錯誤。只有不將大括號寫在行首,避免 JavaScript 將其解釋爲代碼塊,才能解決這個問題。

// 正確的寫法
let x;
({x} = {x: 1});

上面代碼將整個解構賦值語句,放在一個圓括號裏面,就能夠正確執行。關於圓括號與解構賦值的關係,參見下文。

解構賦值容許等號左邊的模式之中,不放置任何變量名。所以,能夠寫出很是古怪的賦值表達式。

({} = [true, false]);
({} = 'abc');
({} = []);

上面的表達式雖然毫無心義,可是語法是合法的,能夠執行。

對象的解構賦值,能夠很方便地將現有對象的方法,賦值到某個變量。

let { log, sin, cos } = Math;

上面代碼將Math對象的對數、正弦、餘弦三個方法,賦值到對應的變量上,使用起來就會方便不少。

因爲數組本質是特殊的對象,所以能夠對數組進行對象屬性的解構

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

上面代碼對數組進行對象解構。數組arr0鍵對應的值是1[arr.length - 1]就是2鍵,對應的值是3。方括號這種寫法,屬於「屬性名錶達式」。

                                                                                                       

若是想跟着振丹繼續學習,能夠微信關注【振丹敲代碼】(微信號:JandenCoding)

新博文微信同步推送,還附有講解視頻哦~

也可直接掃描下方二維碼關注。

相關文章
相關標籤/搜索