4-1.对象的分类
Es6中的对象分类:
- 普通对象:具有
JavaScript
对象所有的默认内部行为。 - 特异对象:具有某些与默认行为不符的内部行为。
- 标准对象:
ECMAScript6
规范中定义的对象,例如,Array
、Date
等。标准对象既可以是普通对象,也可以是特异对象。 - 内建对象:脚本开始执行时存在于
JavaScript
执行环境中的对象,所有标准对象都是内建对象。
4-2.对象字面量语法扩展
4-2-1.对象属性简写
js
var name = 'yxp'
var obj = {
name
}
4-2-2.对象方法简写
js
var obj = {
name: 'yxp',
getName(name) {
console.log(this.name)
}
}
4-2-3.可计算属性名
js
var property = 'name'
var obj = {
[property]: 'yxp'
}
console.log(obj)
4-3.重复的对象字面量属性
在 Es5
的严格模式中,对象字面量当中重复的同名属性,会抛出错误。
js
"use strict"
var person = {
name: 'Tom',
name: 'Jerry'
}
而在 Es6
当中,重复的对象字面量,会取值最后一位属性。
上例代码中, name
属性会取值 Jerry
。
4-4.自有属性枚举顺序
基本规则是:
- 所有数字键按照升序排序。
- 所有字符串键按照它们被加入对象的顺序排序。
- 所有
symbol
键按照它们被加入对象的顺序排序。
该规则主要影响 Object.getOwnPropertyNames()
方法及 Reflect.ownKeys
返回属性的方式。
Object.assign()
方法处理属性的顺序也将随之改变。
而 for...in
、Object.keys()
和 JSON.stringify()
方法的枚举顺序则不确定,跟各大浏览器厂商的指定标准相关。
js
var obj = {
a: 'a',
2: '2',
1: '1',
c: 'c',
b: 'b'
}
// Object.getOwnPropertyNames
var propertyNames = Object.getOwnPropertyNames(obj)
console.log(propertyNames) // ['1', '2', 'a', 'c', 'b']
// for...in
for (var k in obj) {
console.log(k)
}
// Object.keys
var keys = Object.keys(obj)
console.log(keys)
4-5.简化原型访问的 Super
引用
Super
引用相当于指向对象原型的指针。
js
var person = {
getGreeting () {
return 'hello'
}
}
var dog = {
getGreeting () {
return 'woof'
}
}
var friend = {
getGreeting () {
// Object.getPrototypeOf(this).getGreeting.call(this) 等于 super.getGreeting()
return Object.getPrototypeOf(this).getGreeting.call(this) + ', friend'
}
}
// friend的原型指向person
Object.setPrototypeOf(friend, person)
friend.getGreeting()
// friend的原型指向dog
Object.setPrototypeOf(friend, dog)
friend.getGreeting()
- 必须要在使用简写方法的对象中使用
Super
引用。
js
var person = {
getGreeting () {
return 'hello'
}
}
var friend = {
getGreeting: function () {
return super.getGreeting() + ', hi'
}
}
Object.setPrototypeOf(friend, person)
friend.getGreeting() // Uncaught SyntaxError: 'super' keyword unexpected here
Super
处理多重继承,非常有用。因为Super
引用不是动态化的,它总是指向正确的对象。
js
var person = {
getGreeting () {
return 'hello'
}
}
var friend = {
getGreeting () {
// Object.getPrototypeOf(this).getGreeting.call(this) 出错,而 super.getGreeting() 会成功。
// return Object.getPrototypeOf(this).getGreeting.call(this) + ', friend'
return super.getGreeting() + ', friend'
}
}
// friend的原型指向person
Object.setPrototypeOf(friend, person)
friend.getGreeting()
// 再创建一个对象 其原型指向friend
var relativer = Object.create(friend)
relativer.getGreeting()
// 由于this的指向问题,使用 Object.getPrototypeOf(this).getGreeting.call(this) 会报错:Uncaught RangeError: Maximum call stack size exceeded
// 使用 super.getGreeting() 会正常打印 'hello friend'
4-6.HomeObject
JavaScript
所有的函数都有一个名为 [[HomeObject]]
的属性。但并不是所有函数的该属性都有值。
js
// obj.getGreeting.[[HomeObject]] = obj
var obj = {
getGreeting () {}
}
// Obj.prototype.getGreeting.[[HomeObject]] = Obj.prototype
class Obj {
getGreeting () {}
}
// fn.[[HomeObject]] = undefined
function fn () {}
该属性在使用 super
的情况下特别有用。
当在函数内部调用 super
时,会先根据该函数的 [[HomeObject]]
定位到该函数的实际拥有者。
然后再利用 Object.getPrototypeOf()
定位到原型引用。