对象 | 对象属性的类型
ECMA-262 使用一些内部特性来描述属性的特征。这些特性是由为JavaScript 实现引擎的规范定义的。因此,开发者不能在JavaScript 中直接访问这些特性。为了将某个特性标识为内部特性,规范会用两个中括号把特性的名称括起来,比如[[Enumerable]]。
属性分为两种:数据属性和访问属性
数据属性
(1)[[Configurable]]
表示属性是否可以通过delete 删除并重新定义,是否可以修改它的特性,以及是否可以把它改为访问器属性
默认情况下,所有直接定义在对象上的属性的这个特性都是true
注意:一个属性被定义为不可配置(即)configurable=false
后,就不能再变回之前的可配置了configurable=true
(2)[[Enumerable]]
表示属性是否可以通过for-in 循环返回(心里默念:for…in用于遍历对象上可枚举属性,包括原型上的可枚举属性,巴拉巴拉~)
默认情况下,所有直接定义在对象上的属性的这个特性都是true
(3)[[Writable]]
表示属性的值是否可以被修改
默认情况下,所有直接定义在对象上的属性的这个特性都是true
(4)[[Value]]
包含属性实际的值
这个特性的默认值为undefined
数据属性总结与应用
将属性显式添加到对象之后,
[[Configurable]]
、[[Enumerable]]
和[[Writable]]
都会被设置为true
,而[[Value]]
特性会被设置为指定的值用
Object.defineProperty()
修改属性的默认特性1
2
3
4
5Object.defineProperty(obj, prop, descriptor);
- obj: 要定义属性的对象
- prop: 要定义或修改的属性的名称或Symbol
- descriptor: 要定义或修改的属性描述符1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16let person = {};
Object.defineProperty(person, 'name', {
writable: false,
value: 'Katrina',
});
console.log(person.name); // Katrina
person.name = 'Jack';
console.log(person.name); // Katrina
/*
因为设置了writable: false,说明name属性的值不可以被修改
非严格模式,忽略
严格模式,抛出错误
*/一个属性被定义为不可配置(即)
configurable=false
后,就不能再变回之前的可配置了configurable=true
1
2
3
4
5
6
7
8
9
10
11
12let person = {};
Object.defineProperty(person, 'name', {
configurable: false,
value: 'Katrina',
});
// 抛出错误
Object.defineProperty(person, 'name', {
configurable: true,
value: 'Katrina',
});在调用
Object.defineProperty()
时,configurable、enumerable 和writable 的值如果不指定,则都默认为false1
2
3
4
5
6
7
8
9
10
11
12
13
14
15let person = {};
Object.defineProperty(person, 'name', {
value: 'Katrina',
});
console.log(person.name); // Katrina
person.name = 'Jack';
console.log(person.name); // Katrina 说明writable: false
delete person.name;
console.log(person.name); // Katrina 说明configurable: false
for (let k in person) {
console.log(k) // 啥也没有 说明enumerable: false
};
访问器属性
访问器属性包含一个获取(getter)函数和一个设置(setter)函数
- 在读取访问器属性时,会调用获取函数,这个函数的责任就是返回一个有效的值
- 在写入访问器属性时,会调用设置函数并传入新值,这个函数必须决定对数据做出什么修改
访问器属性是不能直接定义的,必须使用
Object.defineProperty()
[[Configurable]]
表示属性是否可以通过delete 删除并重新定义,是否可以修改它的特性,以及是否可以把它改为数据属性
默认情况下,所有直接定义在对象上的属性的这个特性都是true
[[Enumerable]]
表示属性是否可以通过for-in 循环返回
默认情况下,所有直接定义在对象上的属性的这个特性都是true
[[Get]]
获取函数,在读取属性时调用
默认值为undefined。
[[Set]]
设置函数,在写入属性时调用
默认值为undefined
1 | let book = { |
属性访问器的典型使用场景:设置一个属性值会导致一些其他变化发生