这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战
问题
面试官:你能讲讲现在对于对象属性的遍历,有哪些方法?
面试者:可以,有for-in, Object.keys等。
面试官:不错,还有吗?继续?
面试者:额。。。。(我只知道这么多)
面试官:好吧😓 ,那下一个问题
以上场景纯属虚构,可能会有雷同。
今天来学学es6关于对象增加的知识点。
对象
属性遍历
上面我讲了2种,事实上不止2种,我总结一下有五种:(如有遗漏,欢迎评论留言)
-
for-in -
Object.keys -
Object.getOwnPropertyNames -
Object.getOwnPropertySymbols -
Reflect.ownKeys
自从es6新增了Symbol数据类型后,它也可以用来当作对象的属性。所以对象的属性可以是字符串类型和symbol类型。
for-in
这个是遍历对象本身和继承的可枚举属性,不包含symbol类型的属性。
可枚举属性,是指enumerable为true的属性。一般通过赋值定义的属性都是可枚举属性,如果你是通过Object.defineProperty定义属性,如果没有显示指明enumerable为true,则它的可枚举属性就是false(因为enumerable默认值是false)
可以通过Object.getOwnPropertyDescriptor这个属性来获取属性的描述对象(包括枚举属性等)。
对象的本身自带的
toStrng方法就是enumerable属性为false。
var symbol = Symbol('s')
var obj = {
a: 1,
[symbol]: 's'
}
obj.__proto__.b = 2
for(let key in obj) {
console.log(key) // a b 不包含symbol属性
}
var obj = Object.defineProperty({}, 'a', {
value: 1
})
for(let key in obj) {
console.log(key) // b
}
Object.keys
和for-in不同的是,这个只遍历对象本身的可枚举属性,不包含symbol类型的属性。
var symbol = Symbol('s')
var obj = {
a: 1,
[symbol]: 's'
}
obj.__proto__.b = 2
console.log(Object.keys(obj)) // ['a']
Object.getOwnPropertyNames
这个遍历对象本身的可枚举属性和不可枚举属性,不包含symbol类型的属性。
var obj = {
a: 1
}
Object.defineProperty(obj, 'b', {
value: 2,
enumerable: false
})
obj.__proto__.c = 3
console.log(Object.keys(obj)) // ['a']
console.log(Object.getOwnPropertyNames(obj)) // ['a', 'b']
Object.getOwnPropertySymbols
这个是只遍历对象本身的symbol类型的属性。
var symbol = Symbol('s')
var obj = {
a: 1,
[symbol]: 's'
}
console.log(Object.getOwnPropertySymbols(obj)) // [Symbol(s)]
Reflect.ownKeys
这个遍历对象本身的可枚举属性和不可枚举属性,同时也包含symbol类型的属性。
var symbol = Symbol('s')
var obj = {
a: 1,
[symbol]: 's'
}
Object.defineProperty(obj, 'b', {
value: 2,
enumerable: false
})
console.log(Reflect.ownKeys(obj)) // ['a', 'b', Symbol(s)]
super
目前在对象可以使用super关键字,代表的是原型的对象。 不过,目前只支持在对象的方法中使用,而且是简写方法。
var obj = {
a: 1,
fn () {
return super.b
}
}
obj.__proto__.b = 2
console.log(obj.fn()) // 2
var obj = {
a: super.b
}
console.log(obj.a) // error
扩展运算符
扩展运算符之前都是在数组和函数的参数中使用,现在在对象中也可以使用,拷贝对象自身还没分配的属性和值。
var {a, ...obj} = {a:1, b:2, c:3}
console.log(a, obj) // 1 {b: 2, c: 3}
被赋值的时候,扩展运算符只能用在最后。否则会报错。
var {...obj, a} = {a:1, b:2, c:3}
console.log(a, obj) // error
另外扩展运算符是浅拷贝,只能拷贝自身的属性。
// 设置原型对象
var data = Object.create({d:4})
data.a = {b:2}
var {...obj} = data
obj.a.b = 123
console.log(data.a.b) // 123
console.log(obj.d) // undefined
扩展运算符可以用来拷贝对象,合并对象等。
var obj = {a:1}
var obj1 = {b:2}
console.log({...obj, ...obj1}) // {a:1,b:2}
如果存在同名属性,后面的同名属性会覆盖前面的同名属性。
var obj = {a:1}
var obj1 = {a:2}
console.log({...obj, ...obj1}) // {a:2}
扩展运算符用在右边的时候,可以不用在最后。
var obj = {a:1}
console.log({...obj, b: 2}) // {a:1,b:2}