可枚举属性是指那些内部 “可枚举” 标志(enumerable
)设置为 true
的属性,对于通过直接的赋值和属性初始化的属性,该标识值默认为即为 true
,对于通过 Object.defineProperty
,Object.create
等定义的属性,该标识值默认为 false
。可枚举的属性可以通过 for...in
循环进行遍历(除非该属性名是一个 Symbol
)。
属性描述符(Properties’ descriptor)
一个属性描述符是一个记录,由下面属性当中的某些组成的:
- value // 该属性的值(仅针对数据属性描述符有效)
- writable // 当且仅当属性的值可以被改变时为true。(仅针对数据属性描述有效)
- configurable // 当且仅当指定对象的属性描述可以被改变或者属性可被删除时,为true。
- enumerable // 当且仅当指定对象的属性可以被枚举出时,为 true。
- get // 获取该属性的访问器函数(getter)。如果没有访问器, 该值为undefined。(仅针对包含访问器或设置器的属性描述有效)
- set // 获取该属性的设置器函数(setter)。 如果没有设置器, 该值为undefined。(仅针对包含访问器或设置器的属性描述有效)
如下两个方法在添加属性时,都可以指定属性描述符
Object.create(proto, [ propertiesObject ])
方法创建一个拥有指定原型和若干个指定属性的对象。Object.defineProperties(obj, props)
方法在一个对象上添加或修改一个或者多个自有属性,并返回该对象。
|
|
通过 Object.getOwnPropertyDescriptor(obj, prop)
方法可以返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性,也即是实例属性)
可枚举性 enumerable
可枚举性(enumerable
)用来控制所描述的属性。具体来说,如果一个属性的 enumerable
为 false
,下面三个操作不会取到该属性。
for…in
循环Object.keys
方法JSON.stringify
方法
|
|
虽然 enumerable
为 false
的属性通过遍历操作无法获取到,但是我们还是可以直接获取到属性的值,例如 obj.b
原型属性和实例属性
javascript 中属性可以分为:实例属性和原型属性。原型属性是定义在对象的原型(prototype
)中的属性,而实例属性一方面来自构造的函数中,或者是构造函数实例化后添加的新属性。
|
|
如上代码中 obj
的就包含了一个原型属性 d
,还有三个实例属性 a, b, c
(都是可枚举的属性)。
我们注意到 for...in
循环和 Object.keys
方法都可以对对象进行遍历操作,那么二者是否有啥区别呢?执行以下如下代码:
我们可以注意到:for...in
循环可以遍历对象中所有可枚举的对象属性,包括原型属性和实例属性(也就是继承的属性和对象自有属性);而 Object.keys
方法只能遍历出实例属性(也就是对象本身自有的属性)。
而通过 hasOwnProperty
方法就可以区分属性是否是原型属性还是实例属性。
而通过 Object.getOwnPropertyNames(obj)
方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性)组成的数组,但不会获取原型链上的属性。
补充一个知识点:ES6 class 类的内部所有定义的方法,都是不可枚举的(non-enumerable);这一点和 ES5 有点差别(详细内容参考)