复习下es6关于对象增加的知识点

85 阅读3分钟

这是我参与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}

参考

对象的扩展