當對象字面量只有一個屬性的名稱時,JS引擎會在可訪問做用域中查找其同名變量;若是找到則該變量的值被賦給對象字面量裏的同名屬性函數
function createPerson(name, age) { return { name, age } }
var person = { name: 'angela', sayName() { console.log(this.name) } }
在ES5中若是屬性名中包含空格或者是動態的字符串變量做爲屬性名,則須要用[]方括號來訪問,以下所示this
var person = {}, lastName = 'last name'; person["first name"] = 'Li' person[lastName] = 'yun hua'
這種方式適用於屬性名提早已經或可被字符串字面量表示的狀況,若是屬性名「first name」被包含在一個變量中或者須要經過計算才獲得該變量的值
ES6支持了可計算屬性名
比方說上面的代碼ES6可簡化寫成以下:code
let lastName = 'last name'; var person = { "first name": 'Li', [lastName]: 'yun hua' }
甚至方括號中內容一樣可使用表達式做爲屬性的可計算名稱對象
var suffix = 'name' var person = { ['first ' + suffix]: 'Li', ['last ' + suffix]: 'yun hua' }
也就是說任何可用於對象實例括號記法的屬性名一樣能夠做爲對象字面量中計算屬性名排序
因爲全等===有一些特例:一、+0和-0相等 二、NaN和NaN不徹底相等
故ES6引用了Object.is方法來彌補全等運算符的不許備運算
對Object.is方法來講,其運算結果大部分狀況與===運算符相同,惟一區別在於+0和-0被識別爲不相等,NaN和NaN被識別爲相等繼承
Object.assign方法接受任意數量的源對象,並按指定的順序將屬性複製到接收對象中,因此若是多個源對象具備同名屬性,則排位靠後的源對象會覆蓋排位靠前的
有一個須要特別注意的點是Object.assign方法不能將提供者的訪問器屬性複製到接收對象中,因爲Object.assign執行了賦值操做,所以提供者的訪問器屬性最終會被轉變爲接收對象中的一個數據屬性ip
var receiver = {}, supplier = { get name() { return "file.js" } } Object.assign(receiver, supplier) var desc = Object.getOwnPropertyDescriptor(receiver, "name") console.log(desc.value)//file.js console.log(desc.get)//undefined
在ES5嚴格模式下,對於對象字面量重複屬性則會拋出錯誤
但在ES6嚴格模式下,不會報錯,取值會選取最後一個作用域
'use strict' var person = { name: 'lisa', name: 'angela' } console.log(person.name)//angela
全部數字鍵按升序排序字符串
全部字符串按照它們被加入對象的順序排序get
全部symbol鍵按照它們被加入對象的順序排序
var obj = { a: 1, 0: 1, c: 1, 2: 1, b: 1, 1: 1 } obj.d = 1 console.log(Object.getOwnPropertyNames(obj).join(''))//012acbd
ES5中能夠經過Object.getPrototypeOf來返回任意指定對象的原型
ES6中添加了Object.setPrototypeOf來改變任意指定對象的原型
var person = { getGreeting() { return 'hello' } } var dog = { getGreeting() { return 'woof' } } let friend = Object.create(person) console.log(friend.getGreeting())//hello console.log(Object.getPrototypeOf(friend) === person)//true Object.setPrototypeOf(friend, dog) console.log(friend.getGreeting())//woof console.log(Object.getPrototypeOf(friend) === dog)//true
在ES5中若是要調用父類的方法,則通常是經過若是這種方式,也就是得到原型對象再經過call來調用
Object.getPrototypeOf(this).getGreeting.call(this)
var person = { getGreeting() { return 'hello' } } var dog = { getGreeting() { return 'woof' } } var friend = { getGreeting() { return Object.getPrototypeOf(this).getGreeting.call(this) + ",hi!"; } } Object.setPrototypeOf(friend, person) console.log(friend.getGreeting())//hello,hi! console.log(Object.getPrototypeOf(friend) === person)//true Object.setPrototypeOf(friend,dog) console.log(friend.getGreeting())//woof,hi! console.log(Object.getPrototypeOf(friend) === dog)//true
可是在多重繼承的狀況下,上述方法則會出錯,舉例來講
var person = { getGreeting() { return 'hello' } } var friend = { getGreeting() { return Object.getPrototypeOf(this).getGreeting.call(this) + ",hi!"; } } Object.setPrototypeOf(friend, person) var relative = Object.create(friend) console.log(person.getGreeting())//hello console.log(friend.getGreeting())//hello,hi! console.log(relative.getGreeting())// 報錯 Uncaught RangeError: Maximum call stack size exceeded
ES6中經過super關鍵字可輕鬆解決問題
var person = { getGreeting() { return 'hello' } } var friend = { getGreeting() { return super.getGreeting.call(this) + ",hi!"; } } Object.setPrototypeOf(friend, person) var relative = Object.create(friend) console.log(person.getGreeting())//hello console.log(friend.getGreeting())//hello,hi! console.log(relative.getGreeting())// hello,hi
你們可能會疑惑super是怎麼作到知道真正的調用對象是哪一個
這實際上是由於ES6中正式將方法定義爲一個函數,它會有一個內部的[[HomeObject]]屬性來容納這個方法從屬的對象
var person = { // 是方法 getGreeting() { return 'hello' } } function shareGreeting(params) { return 'Hi!' }
person.getGreeting方法的[[HomeObject]]屬性爲person,而shareGreeting函數未將其賦值給一個對象,於是沒有明肯定義其[[HomeObject]]屬性
super的全部引用都經過[[HomeObject]]屬性來肯定後續的運行過程
在[[HomeObject]]屬性上調用Object.getPrototypeOf方法來檢索原型的引用
搜索原型找以同名函數
設置this綁定並調用相應的方法