对象字面量语法扩展
属性初始值的简写
当一个对象的属性与本地变量同名的时候,不必再写冒号和值,只写属性名即可。
function createFunction(name, age) {
return {
name,
age
}
}
对象方法的简写
如果为对象添加方法,则简化为消除冒号和 function 关键字。
let dog = {
name: 'Sugary',
// getName: function () {
// return this.name
// }, // ES5中对象方法的语法
getName() {
return this.name
}
}
可计算属性名
let suffix = 'name'
let person = {
['first' + suffix]: 'Sugary',
['last' + suffix]: 'Nai',
}
console.log(person['firstname']) // Sugary
console.log(person['lastname']) // Nai
新增方法
Object.is()
Object.is() 方法的出现主要是弥补全等运算符(===)的不准确运算。在 JavaScript 中,+0 和 -0 表示的是两个完全不同的实体,但用全等运算符对两者进行比较时,得到的是相同的结果;NaN === NaN 返回的结果是 false, 需要用 isNaN() 方法才可以正确检测 NaN。
console.log(+0 === -0) // true
console.log(NaN === NaN) // false
console.log(Object.is(+0, -0)) // false
console.log(Object.is(NaN)) // false
Object.assign()
该方法表示一个对象接收来自另一个对象的属性和方法。该方法可以接收任意数量的源对象,并按照指定的顺序将属性复制到接收对象中。如果多个源对象具有同名属性,则排位靠后的源对象会覆盖排位靠前的。
let receiver = {}
let supplier1 = {
type: 'js',
name: 'file.js',
}
let supplier2 = {
type: 'css',
}
Object.assign(receiver, supplier1, supplier2)
console.log(receiver) // { type: 'css', name: 'file.js' }
自有属性枚举顺序
ES6 严格规定了自有属性被枚举时的返回顺序,返回顺序的基本规则是:
- 所有数字键按升序排序;
- 所有字符串键按照它们被加入对象的顺序排序;
- 所有 symbol 键按照它们被加入对象的顺序排序。
let myObj = {
a: 1,
0: 1,
c: 1,
2: 1,
b: 1,
1: 1,
}
myObj.d = 1
console.log(Object.getOwnPropertyNames(myObj).join('')) // 012acbd
增强对象的原型
改变对象的原型
- ES5 中用 Object.getPrototypeOf() 方法来返回任意指定对象的原型;
- ES6 中用 Object.setPrototypeOf() 方法,可以改变任意指定对象的原型。
具体方法如下:
let Person = {
getGreeting() {
return 'Hello'
},
}
let 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
简化原型访问的 Super 引用
如果你想重写对象实例的方法,又需要调用与它同名的原型方法。在 ES5 中是这样实现的:
let Person = {
getGreeting() {
return 'Hello'
},
}
let Dog = {
getGreeting() {
return 'Woof'
},
}
let 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
但是这种方法在多重继承的情况下会有问题,会进入递归调用直到触发栈溢出报错。这个时候,我们可以使用 ES6 新引入的关键字 super 。super 引用相当于指向对象原型的指针。
let Person = {
getGreeting() {
return 'Hello'
},
}
let Dog = {
getGreeting() {
return 'Woof'
},
}
let friend = {
getGreeting() {
// 此处是简写方法
// return Object.getPrototypeOf(this).getGreeting.call(this) + ', hi!'
return super.getGreeting() + ', 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
注意:必须要在使用简写方法的对象中使用 Super 引用,否则会报语法错误。
正式的方法定义
ES6 中将方法定义为一个函数,它会有一个内部的 [[HomeObject]] 属性来容纳这个方法从属的对象。
let Person = {
// 是方法
getGreeting() {
return 'Hello'
},
}
// 不是方法
function shareGreeting() {
return 'Hi!'
}
示例中的 getGreeting() 方法的[[HomeObject]] 属性值为 Person,而 shareGreeting() 是没有 [[HomeObject]] 属性的。ES6 定义这个方法主要是为 Super 服务的。Super 的所有引用都通过 [[HomeObject]] 属性来确定后续的运行过程。