问题来源:Object.defineProperty和普通的赋值操作有什么区别?我们都知道像有些操作是会遍历原型链的,但是Object上其实有很多方法和属性,在遍历的时候并没有将其遍历出来,但是他们却是可用的,这里引出概念"可读不可写"
要注意的属性名:
一个对象的属性名可以是任何有效的 JavaScript 字符串,或者可以被转换为字符串的任何类型,包括空字符串。然而,一个属性的名称如果不是一个有效的 JavaScript 标识符(例如,一个由空格或连字符,或者以数字开头的属性名),就只能通过方括号标记访问。这个标记法在属性名称是动态判定(属性名只有到运行时才能判定)时非常有用。
枚举对象的属性:
- for...in:包括链的,访问包括原型链的可枚举属性
- Object.keys(obj):只访问自身的,访问不包括原型链的可枚举属性
- Object.getOwnPropertyNames(obj): 访问自身的不论枚举与否,自身包含的所有属性(不包括原型中)(无论是否可枚举)
默认情况下,使用 Object.defineProperty() 添加的属性值是不可修改(immutable)的。
对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。
共享以下可选键值(默认值是指在使用 Object.defineProperty() 定义属性时的默认值):
-
configurable
true 时,才能够被改变。 默认为 false。 -
enumerable
为 true 时,该属性才会出现在对象的枚举属性中。 默认为 false。
数据描述符
可选键值:
- value
可以是任何有效的 JavaScript 值(数值,对象,函数等)。 默认为 undefined。 - writable
为 true 时,上面的 value,才能被赋值运算符 (en-US)改变。 默认为 false。
存取描述符
即 getter 函数+ setter 函数。
可选键值:
- get
该函数的返回值会被用作属性的值。 默认为 undefined。 - set
当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。 默认为 undefined。
直接赋值和使用Object.defineProperty()的默认值不同
直接赋值:
o.a = 1;
// 等同于:
Object.defineProperty(o, "a", {
value: 1,
writable: true,
configurable: true,
enumerable: true
});
Object.defineProperty():
Object.defineProperty(o, "a", { value : 1 });
// 等同于:
Object.defineProperty(o, "a", {
value: 1,
writable: false,
configurable: false,
enumerable: false
});
configurable 特性表示对象的属性是否可以被删除,以及除 value 和 writable 特性外的其他特性是否可以被修改。
这里的很多属性,如在configrable和numerable,非严格模式下不会报错。
还可以通过Object.defineProperty给原型上加属性。
function myclass() {
}
Object.defineProperty(myclass.prototype, "x", {
get() {
return this.value;
},
set(x) {
this.value = x;
}
});