js之defineProperty
对象属性的类型
ECMA-262 使用一些内部特性来描述属性的特征。这些特性是由为 JavaScript 实现引擎的规范定义的。因此,开发者不能在 JavaScript 中直接访问这些特性。为了将某个特性标识为内部特性,规范会用两个中括号把特性的名称括起来,比如[[Enumerable]]。
属性分两种:数据属性 和 访问器属性,它们共享 configurable、enumerable 特性。属性只能是这两种类型之一,不能同时为两者。
数据属性
数据属性包含一个保存数据值的位置。值会从这个位置读取,也会写入到这个位置。数据属性有 4 个特性描述它们的行为:
- [[Configurable]]:表示属性是否可以通过
delete删除并重新定义,是否可以修改它的特性,以及是否可以把它改为访问器属性。默认情况下,所有直接定义在对象上的属性的这个特性都是 true。 - [[Enumerable]]:表示属性是否可以通过 for-in 循环返回。默认情况下,所有直接定义在对象上的属性的这个特性都是 true。
- [[Writable]]:表示属性的值是否可以被修改。默认情况下,所有直接定义在对象上的属性的这个特性都是 true。
- [[Value]]:包含属性实际的值。

访问器属性
访问器属性是不能直接定义的,必须使用 Object.defineProperty()。
访问器属性不包含数据值。相反,它们包含一个获取(getter)函数和一个设置(setter)函数,不过这两个函数不是必需的。在读取访问器属性时,会调用获取函数,这个函数的责任就是返回一个有效的值。在写入访问器属性时,会调用设置函数并传入新值,这个函数必须决定对数据做出什么修改。
访问器属性有 4 个特性描述它们的行为:
- [[Configurable]]:表示属性是否可以通过
delete删除并重新定义,是否可以修改它的特性,以及是否可以把它改为数据属性。默认情况下,所有直接定义在对象上的属性的这个特性都是 true。 - [[Enumerable]]:表示属性是否可以通过 for-in 循环返回。默认情况下,所有直接定义在对象上的属性的这个特性都是 true。
- [[Get]]:获取函数,在读取属性时调用。默认值为 undefined。
- [[Set]]:设置函数,在写入属性时调用。默认值为 undefined。
属性
要修改属性的默认特性,就必须使用 Object.defineProperty() 方法。这个方法接收 3 个参数:
- obj:要定义属性的对象。
- prop:一个字符串或 Symbol,指定了要定义或修改的属性键。
- descriptor:要定义或修改的属性的描述符。
Object.defineProperty() 允许精确地添加或修改对象上的属性, 默认情况下,使用 Object.defineProperty() 添加的属性是不可写、不可枚举和不可配置的。
1 | |

Configurable 特性
configurable 特性控制属性是否可以从对象中删除以及其特性(除了 value 和 writable)是否可以更改。
把 configurable 设置为 false,意味着这个属性不能从对象上删除。此外,一个属性被定义为不可配置之后,就不能再变回可配置的了。
1 | |

Enumerable 特性
enumerable 特性定义了属性是否可以被 Object.assign() 或展开运算符所考虑。对于非 Symbol 属性,它还定义了属性是否会在 for…in 循环和 Object.keys() 中显示。
1 | |

Writable 特性
当 writable 特性设置为 false 且 configurable 特性设置为 false 时,该属性被称为“不可写的”。它不能被重新赋值。尝试对一个不可写的属性进行写入不会改变它,在严格模式下还会导致错误。

当 writable 特性设置为 false 且 configurable 特性设置为 true 时,该属性的 value 仍然可以使用 defineProperty 进行替换(但不能使用赋值运算符)。

setter 和 getter 特性
-
get:用作属性
getter的函数,如果没有getter则为undefined。当访问该属性时,将不带参地调用此函数,并将 this 设置为通过该属性访问的对象(因为可能存在继承关系,这可能不是定义该属性的对象)。返回值将被用作该属性的值。 -
set:用作属性
setter的函数,如果没有setter则为undefined。当该属性被赋值时,将调用此函数,并带有一个参数(要赋给该属性的值),并将 this 设置为通过该属性分配的对象。默认值为undefined。
1 | |

参考文档
- MDN
- 《JavaScript 高级程序设计 第4版》