输出是什么?
const person = { name: "Lydia" };
Object.defineProperty(person, "age", { value: 21 });
console.log(person);
console.log(Object.keys(person));
A: { name: “Lydia”, age: 21 }, [“name”, “age”]
B: { name: “Lydia”, age: 21 }, [“name”]
C: { name: “Lydia”}, [“name”, “age”]
D: { name: “Lydia”}, [“age”]
答案: B
通过defineProperty方法,我们可以给对象添加一个新属性,或者修改已经存在的属性。而我们使用defineProperty方法给对象添加了一个属性之后,属性默认为 不可枚举(not enumerable). Object.keys方法仅返回对象中 可枚举(enumerable) 的属性,因此只剩下了"name".
用defineProperty方法添加的属性默认不可变。你可以通过writable, configurable 和 enumerable属性来改变这一行为。这样的话, 相比于自己添加的属性,defineProperty方法添加的属性有了更多的控制权。
普通的对象属性对应的属性描述符含有:writable(可写)、enumerable(可枚举)和configurable(可配置)。
1.在使用Object.defineProperty()、Object.defineProperties() 或 Object.create() 函数的情况下添加数据属性,writable、enumerable和configurable默认值为false。
2.使用对象直接量创建的属性,writable、enumerable和configurable特性默认为true。
writable
writable属性是一个布尔值,决定了目标属性的值(value)是否可以被改变。如果原型对象的某个属性的writable为false,那么子对象将无法自定义这个属性。
enumerable
enumerable(可遍历性)返回一个布尔值,表示目标属性在 for…in、Object.keys、JSON.stringify 中是否可遍历。但是可以直接获取它的值。
注意,for…in循环包括继承的属性,Object.keys方法不包括继承的属性。如果需要获取对象自身的所有属性,不管是否可遍历,可以使用Object.getOwnPropertyNames方法。
configurable
configurable(可配置性)返回一个布尔值,决定了是否可以修改属性描述对象。
也就是说,configurable为false时,value、writable、enumerable和configurable都不能被修改了, configurable修改成false是单向操作,无法撤销!以及无法被删除
注意,writable只有在false改为true会报错,true改为false是允许的。
至于value,只要writable和configurable有一个为true,就允许改动。
另外,configurable为false时,直接目标属性赋值,不报错,但不会成功。