JS对象属性探究

对象

ECMAScript 将对象的属性分为数据属性和访问器属性,属性描述符有两种主要形式:数据描述符和存取描述符,
使用defineProperty可以为对象已有的属性添加特性描述:

1
2
3
4
5
6
7
8
9
10
var obj = {
test:"hello"
}
//对象已有的属性添加特性描述
Object.defineProperty(obj,"test",{
configurable:true | false, // 是否可以删除目标属性或是否可以再次修改属性的特性(writable, configurable, enumerable)
enumerable:true | false, // 是否可枚举
value:任意类型的值,
writable:true | false // 属性的值是否可以被重写
});

ES5有三个操作会忽略enumerable为false的属性:

  • for…in循环:只遍历对象自身的和继承的可枚举的属性
  • Object.keys():返回对象自身的所有可枚举的属性的键名
  • JSON.stringify():只串行化对象自身的可枚举的属性

Object.getOwnPropertyNames获取该对象不包括原型链所有的属性包括不可枚举的
ES6新增了一个操作Object.assign(),会忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性。

1
2
3
4
5
6
7
8
9
Object.getOwnPropertyDescriptor(Object.prototype, 'toString').enumerable
// false

Object.prototype.propertyIsEnumerable('toString') // false

Object.getOwnPropertyDescriptor([], 'length').enumerable
// false

[].propertyIsEnumerable('length') // false

toString和length属性的enumerable都是false,因此for…in不会遍历到这两个继承自原型的属性。

当使用了getter或setter方法,不允许使用writable和value这两个属性。

ES5 环境,Object.keys如果传入的参数不是一个对象,而是一个字符串,那么它会报 TypeError。在 ES6 环境,如果传入的是一个非对象参数,内部会对参数作一次强制对象转换,如果转换不成功会抛出 TypeError。

1
2
3
4
5
// 在 ES5 环境
Object.keys('foo'); // TypeError: "foo" is not an object

// 在 ES6 环境
Object.keys('foo'); // ["0", "1", "2"]

参考链接: