Javascript 对象属性配置
Zhongjun Qiu 元婴开发者

JavaScript 中对象属性的 writable、enumerable、configurable 标志及其默认行为;演示属性描述符的获取与定义方法;简要说明 getter 和 setter 的用法及访问器属性的特点。

属性标志

对象属性(properties),除 value 外,还有三个特殊的特性(attributes),也就是所谓的“标志”:

  • writable — 如果为 true,则值可以被修改,否则它是只可读的。
  • enumerable — 如果为 true,则会被在循环中列出,否则不会被列出。
  • configurable — 如果为 true,则此属性可以被删除,这些特性也可以被修改,否则不可以。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let user = {
name: "John"
};

let descriptor = Object.getOwnPropertyDescriptor(user, 'name');

alert( JSON.stringify(descriptor, null, 2 ) );
/* 属性描述符:
{
"value": "John",
"writable": true,
"enumerable": true,
"configurable": true
}
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let user = {};

Object.defineProperty(user, "name", {
value: "John"
});

let descriptor = Object.getOwnPropertyDescriptor(user, 'name');

alert( JSON.stringify(descriptor, null, 2 ) );
/*
{
"value": "John",
"writable": false,
"enumerable": false,
"configurable": false
}
*/

不提供标志,默认创建的标志都为false。

请注意:configurable: false 防止更改和删除属性标志,但是允许更改属性的值。

对于不可配置的属性,我们可以将 writable: true 更改为 false,从而防止其值被修改(以添加另一层保护)。

1
2
3
4
5
Object.defineProperties(user, {
name: { value: "John", writable: false },
surname: { value: "Smith", writable: false },
// ...
});

通常,当我们克隆一个对象时,我们使用赋值的方式来复制属性,像这样:

1
2
3
for (let key in user) {
clone[key] = user[key]
}

……但是,这并不能复制标志。所以如果我们想要一个“更好”的克隆,那么 Object.defineProperties 是首选。

1
let clone = Object.defineProperties({}, Object.getOwnPropertyDescriptors(obj));

另一个区别是 for..in 会忽略 symbol 类型的和不可枚举的属性,但是 Object.getOwnPropertyDescriptors 返回包含 symbol 类型的和不可枚举的属性在内的 所有 属性描述符。

getter 和 setter

访问器属性由 “getter” 和 “setter” 方法表示。在对象字面量中,它们用 getset 表示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let user = {
name: "John",
surname: "Smith",

get fullName() {
return `${this.name} ${this.surname}`;
},

set fullName(value) {
[this.name, this.surname] = value.split(" ");
}
};

// set fullName 将以给定值执行
user.fullName = "Alice Cooper";

alert(user.name); // Alice
alert(user.surname); // Cooper

从外表看,访问器属性看起来就像一个普通属性。这就是访问器属性的设计思想。我们不以函数的方式 调用 user.fullName,我们正常 读取 它:getter 在幕后运行。

 REWARD AUTHOR
 Comments
Comment plugin failed to load
Loading comment plugin