在接收數據的地方(好比賦值的左邊),解構使你使用模式去獲取部分數據。數組
下面的代碼是解構的一個例子:瀏覽器
let obj = { first: 'Jane', last: 'Doe' }; let { first: f, last: l } = obj; // (A)
// f = 'Jane'; l = 'Doe'
在行 A 解構了 obj
:經過左邊的模式,運用賦值操做符(=)從裏面獲取數據,並將數據賦值給變量 f
和 l
。這些變量事先自動聲明好,由於該行以 let
開始。函數
也能夠解構數組:spa
let [x, y] = ['a', 'b']; // x = 'a'; y = 'b'
解構能夠用於下列情形:prototype
// Variable declarations:解構賦值不只適用於var命令,也適用於let和const命令。
let [x] = ['a']; const [x] = ['a']; var [x] = ['a']; // Assignments:
[x] = ['a']; // Parameter definitions:
function f([x]) { ··· } f(['a']);
也能夠在一個 for-of
循環中解構:code
// Handled like a variable declaration:
for (let [k,v] of arr.entries()) ··· // Handled like an assignment
for ({name: n, age: a} of arr) ···
(1)Rest解構賦值對象
對象的Rest解構賦值用於從一個對象取值,至關於將全部可遍歷的、但還沒有被讀取的屬性,分配到指定的對象上面。全部的鍵和它們的值,都會拷貝到新對象上面。blog
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }; x // 1 y // 2 z // { a: 3, b: 4 }
上面代碼中,變量z
是Rest解構賦值所在的對象。它獲取等號右邊的全部還沒有讀取的鍵(a
和b
),將它們和它們的值拷貝過來。排序
因爲Rest解構賦值要求等號右邊是一個對象,因此若是等號右邊是undefined
或null
,就會報錯,由於它們沒法轉爲對象。繼承
let { x, y, ...z } = null; // 運行時錯誤 let { x, y, ...z } = undefined; // 運行時錯誤
Rest解構賦值必須是最後一個參數,不然會報錯。
let { ...x, y, z } = obj; // 句法錯誤 let { x, ...y, ...z } = obj; // 句法錯誤
上面代碼中,Rest解構賦值不是最後一個參數,因此會報錯。
解構賦值雖然很方便,可是解析起來並不容易。對於編譯器來講,一個式子究竟是模式,仍是表達式,沒有辦法從一開始就知道,必須解析到(或解析不到)等號才能知道。
由此帶來的問題是,若是模式中出現圓括號怎麼處理。ES6的規則是,只要有可能致使解構的歧義,就不得使用圓括號。
變量聲明語句中,不能帶有圓括號。
函數參數中,模式不能帶有圓括號。
賦值語句中,不能將整個模式,或嵌套模式中的一層,放在圓括號之中。
交換變量的值
從函數返回多個值
函數參數的定義
提取JSON數據
函數參數的默認值
遍歷Map結構
輸入模塊的指定方法
總結:
若是解構不成功,變量的值就等於undefined
。
不徹底解構,即等號左邊的模式,只匹配一部分的等號右邊的數組。這種狀況下,解構依然能夠成功。
解構賦值容許指定默認值。
對象的解構與數組有一個重要的不一樣。數組的元素是按次序排列的,變量的取值由它的位置決定;而對象的屬性沒有次序,變量必須與屬性同名,才能取到正確的值。
默認值生效的條件是,對象的屬性值嚴格等於undefined
。
解構賦值時,若是等號右邊是數值和布爾值,則會先轉爲對象。因爲undefined
和null
沒法轉爲對象,因此對它們進行解構賦值,都會報錯。
方法定義:
let obj = { myMethod(x, y) { ··· } };
屬性值縮寫:
let first = 'Jane'; let last = 'Doe'; let obj = { first, last }; // Same as:
let obj = { first: first, last: last };
計算屬性鍵:
let propKey = 'foo'; let obj = { [propKey]: true, ['b'+'ar']: 123 };
這種新語法也可用於方法定義:
let obj = { ['h'+'ello']() { return 'hi'; } }; console.log(obj.hello()); // hi
計算屬性鍵主要的應用場景就是使 symbol 成爲屬性鍵變得更加方便。
Object
中的新方法Object
中最重要的新方法是 assign()
。習慣上,在 JavaScript 的世界中,這個函數叫作 extend()
。 Object.assign()
僅考慮自有(非繼承)屬性。
let obj = { foo: 123 }; Object.assign(obj, { bar: true }); console.log(JSON.stringify(obj)); // {"foo":123,"bar":true}
常見用途:
(1)爲對象添加屬性
(2)爲對象添加方法
(3)克隆對象
(4)合併多個對象
(5)爲屬性指定默認值
ES6一共有6種方法能夠遍歷對象的屬性。
(1)for...in
for...in
循環遍歷對象自身的和繼承的可枚舉屬性(不含Symbol屬性)。
(2)Object.keys(obj)
Object.keys
返回一個數組,包括對象自身的(不含繼承的)全部可枚舉屬性(不含Symbol屬性)。
(3)Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames
返回一個數組,包含對象自身的全部屬性(不含Symbol屬性,可是包括不可枚舉屬性)。
(4)Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols
返回一個數組,包含對象自身的全部Symbol屬性。
(5)Reflect.ownKeys(obj)
Reflect.ownKeys
返回一個數組,包含對象自身的全部屬性,無論是屬性名是Symbol或字符串,也無論是否可枚舉。
(6)Reflect.enumerate(obj)
Reflect.enumerate
返回一個Iterator對象,遍歷對象自身的和繼承的全部可枚舉屬性(不含Symbol屬性),與for...in
循環相同。
以上的6種方法遍歷對象的屬性,都遵照一樣的屬性遍歷的次序規則。
注意,語言規範把索引定義爲字符串鍵,當轉換成無符號整數而後再轉換回來,仍然是一樣的字符串(一樣也必須比232-1小,所以數組是有長度限制的)。這意味着規範把數組索引看做字符串鍵,甚至普通的對象均可以有數組索引:
Reflect.ownKeys({ [Symbol()]:0, b:0, 10:0, 2:0, a:0 }) //['2', '10', 'b', 'a', Symbol()]
__proto__
屬性,Object.setPrototypeOf(),Object.getPrototypeOf()(1)__proto__
屬性
__proto__
屬性(先後各兩個下劃線),用來讀取或設置當前對象的prototype
對象。目前,全部瀏覽器(包括IE11)都部署了這個屬性。
在實現上,__proto__
調用的是Object.prototype.__proto__。
(2)Object.setPrototypeOf()
Object.setPrototypeOf
方法的做用與__proto__
相同,用來設置一個對象的prototype
對象。它是ES6正式推薦的設置原型對象的方法。
// 格式 Object.setPrototypeOf(object, prototype) // 用法 var o = Object.setPrototypeOf({}, null);
該方法等同於下面的函數。
function (obj, proto) { obj.__proto__ = proto; return obj; }
(3)Object.getPrototypeOf()
該方法與setPrototypeOf方法配套,用於讀取一個對象的prototype對象。
ES5引入了Object.keys
方法,返回一個數組,成員是參數對象自身的(不含繼承的)全部可遍歷(enumerable)屬性的鍵名。
Object.values
方法返回一個數組,成員是參數對象自身的(不含繼承的)全部可遍歷(enumerable)屬性的鍵值。
Object.entries
方法返回一個數組,成員是參數對象自身的(不含繼承的)全部可遍歷(enumerable)屬性的鍵值對數組。