主要知識點有對象類別、屬性速記法、方法簡寫、需計算屬性名、Object.is()方法、Object.assign()方法、可容許重複的屬性、自有屬性的枚舉順序、Object.setPrototypeOf()方法、super引用、方法定義
![]()
《深刻理解ES6》筆記 目錄java
屬性初始化器的速記法能夠用來消除屬性名和本地變量的重複狀況,可使用做用域內的變量值賦值給同名屬性:segmentfault
ES5 及更早版本中:函數
function createPerson(name, age) { return { name: name, age: age }; }
ES6簡寫:this
function createPerson(name, age) { return { name, age }; }
在對象字面量的寫法中,爲一個對象添加一個方法,須要指定對象的屬性以及具體的函數聲明。ES6提供了一種方法簡寫語法,經過省略function關鍵字,可以讓爲對象添加方法的語法更加簡潔。
ES5中的寫法:spa
var person = { name: "Nicholas", sayName: function() { console.log(this.name); } };
ES6簡寫語法:3d
var person = { name: "Nicholas", sayName() { console.log(this.name); } };
需計算屬性名規則容許對象字面量中屬性名是變量、字符串字面量或者由變量計算而得的,具體寫法是經過方括號[]包含屬性名。code
var lastName = "last name"; var person = { "first name": "Nicholas", [lastName]: "Zakas" }; console.log(person["first name"]); // "Nicholas" console.log(person[lastName]); // "Zakas" var suffix = " name"; var person = { ["first" + suffix]: "Nicholas", ["last" + suffix]: "Zakas" }; console.log(person["first name"]); // "Nicholas" console.log(person["last name"]); // "Zakas" const id = 5 const obj = { [`my-${id}`]: id } console.log(obj['my-5']) // 5
JS中比較兩個值是否相同的時候會使用嚴格等於運算符===,可是,使用嚴格運算符式,+0和-0會認爲這二者是相等的,而NaN===NaN是不相等的,使用Object.is()方法來判斷這二者狀況與使用嚴格相等符會有所不一樣,其餘狀況和使用嚴格相等運算符基本一致;對象
console.log(+0 == -0); // true console.log(+0 === -0); // true console.log(Object.is(+0, -0)); // false console.log(NaN == NaN); // false console.log(NaN === NaN); // false console.log(Object.is(NaN, NaN)); // true console.log(5 == 5); // true console.log(5 == "5"); // true console.log(5 === 5); // true console.log(5 === "5"); // false console.log(Object.is(5, 5)); // true console.log(Object.is(5, "5")); // false
混入( Mixin )是在 JS 中組合對象時最流行的模式。在一次混入中,一個對象會從另外一個對象中接收屬性與方法。
下面是一個mixin方法的實現,這個方法實現的是淺拷貝。將b對象的屬性拷貝到了a對象,合併成一個新的對象。blog
//mixin不僅有這一種實現方法。 function mixin(receiver, supplier) { Object.keys(supplier).forEach((key) => { receiver[key] = supplier[key] }) return receiver } let a = {name: 'sb'}; let b = { c: { d: 5 } } console.log(mixin(a, b)) // {"name":"sb","c":{"d":5}}
寫這樣一個mixin方法是否是很煩,並且每一個項目都得引入這個方法,如今,ES6給咱們提供了一個現成的方法Object.assign()來作mixin的事情。圖片
假設要實現上面的mixin方法,你只須要給Object.assign()傳入參數便可。
console.log(Object.assign(a, b))// {"name":"sb","c":{"d":5}}
ES5 嚴格模式爲重複的對象字面量屬性引入了一個檢查,若找到重複的屬性名,就會拋出錯誤。
"use strict"; var person = { name: "Nicholas", name: "Greg" // 在 ES5 嚴格模式中是語法錯誤 };
ES6 移除了重複屬性的檢查,嚴格模式與非嚴格模式都再也不檢查重複的屬性。當存在重複屬性時,排在後面的屬性的值會成爲該屬性的實際值:
"use strict"; var person = { name: "Nicholas", name: "Greg" // 在 ES6 嚴格模式中不會出錯 }; console.log(person.name); // "Greg"
ES5 並無定義對象屬性的枚舉順序,而是把該問題留給了 JS 引擎廠商。而 ES6 則嚴格定義了對象自有屬性在被枚舉時返回的順序。這對 Object.getOwnPropertyNames() 與Reflect.ownKeys)如何返回屬性形成了影響,還一樣影響了Object.assign() 處理屬性的順序。
自有屬性枚舉時基本順序以下:
const state = { id: 1, 5: 5, name: "eryue", 3: 3 } Object.getOwnPropertyNames(state) //["3","5","id","name"] 枚舉key Object.assign(state, null) //{"3":3,"5":5,"id":1,"name":"eryue"}
for-in 循環的枚舉順序仍未被明確規定,由於並不是全部的 JS 引擎都採用相同的方式。而 Object.keys() 和 JSON.stringify() 也使用了與 for-in 同樣的枚舉順序。
通常來講,對象的原型會在經過構造器或 Object.create() 方法建立該對象時被指定。
ES5 添加了 Object.getPrototypeOf() 方法來從任意指定對象中獲取其原型;
缺乏在初始化以後更改對象原型的標準方法。
ES6 經過添加 Object.setPrototypeOf() 方法而改變了這種假定,此方法容許你修改任意指定對象的原型。它接受兩個參數:須要被修改原型的對象,以及將會成爲前者原型的對象。
let person = { getGreeting() { return "Hello"; } }; let dog = { getGreeting() { return "Woof"; } }; // 原型爲 person let friend = Object.create(person); console.log(friend.getGreeting()); // "Hello" console.log(Object.getPrototypeOf(friend) === person); // true // 將原型設置爲 dog Object.setPrototypeOf(friend, dog); console.log(friend.getGreeting()); // "Woof" console.log(Object.getPrototypeOf(friend) === dog); // true
可以使用super引用,來訪問原型中的方法:
const proto = { foo: 'hello' }; const obj = { foo: 'world', find() { return super.foo; } }; Object.setPrototypeOf(obj, proto); obj.find() // "hello"
注意,super關鍵字表示原型對象時,只能用在對象的簡寫方法之中,用在其餘地方都會報錯。
// 報錯 const obj = { foo: super.foo } // 報錯 const obj = { foo: () => super.foo } // 報錯 const obj = { foo: function () { return super.foo } }
javaScript 引擎內部,super.foo等同於Object.getPrototypeOf(this).foo(屬性)或Object.getPrototypeOf(this).foo.call(this)(方法)。
const proto = { x: 'hello', foo() { console.log(this.x); }, }; const obj = { x: 'world', foo() { super.foo(); } } Object.setPrototypeOf(obj, proto); obj.foo() // "world"
上面代碼中,super.foo指向原型對象proto的foo方法,可是綁定的this卻仍是當前對象obj,所以輸出的就是world。
ES6 則正式作出了定義:方法是一個擁有 [[HomeObject]] 內部屬性的函數,此內部屬性指向該方法所屬的對象。
let person = { // 方法 getGreeting() { return "Hello"; } }; // 並不是方法 function shareGreeting() { return "Hi!"; }
大多數狀況下,這種差別並不重要,然而使用 super 引用時就徹底不一樣了。
let person = { getGreeting() { return "Hello"; } }; // 原型爲 person let friend = { getGreeting() { return super.getGreeting() + ", hi!"; } }; Object.setPrototypeOf(friend, person); console.log(friend.getGreeting()); // "Hello, hi!"