# 属性的描述符
在 JavaScript 中我们用属性来描述一个对象,同时属性也可以细分为两种:数据属性 和 访问器属性。每种属性都带有自个的属性描述符,简单来说这些描述符就是属性的属性。
# 数据描述符
# configurable(可配置)
- 默认值:false
- 能否通过 delete 删除属性
- 能否修改属性的描述符或者将属性改为访问器属性
# enumerable(可枚举)
- 默认值:false
- 能否通过 for-in 返回属性
# writable(可写入)
- 默认值:false
- 能否修改属性的值
# value(属性值)
- 默认值:undefined
- 属性的值
# 访问器描述符
访问器属性也带有 configurable 和 enumerable ,除此之外,再加下面两个描述符
# get
- 默认值:undefined
- 读取属性时调用的函数
# set
- 默认值:undefined
- 给属性赋值时调用的函数
# 定义和获取属性描述符
# 定义属性描述符
# Object.defineProperty(obj, key, descriptor)
- obj:属性所在对象
- key:属性的名字
- descriptor:属性的描述符对象
# Object.defineProperties(obj, props)
- obj:属性所在对象
- props:多个属性的描述符对象组成的对象
# 获取属性描述符
# Object.getOwnPropertyDescriptor(obj, key)
- obj:属性所在对象
- key:属性的名字
# 举个🌰
# 定义一个对象
var person = {
name: 'randy'
}
1
2
3
2
3
对象 person 带有一个 name 属性,其值为 randy 。
# 获取属性描述符
console.log(Object.getOwnPropertyDescriptor(person, 'name'););
// 控制台打印如下:
{
configurable: true,
enumerable: true,
writable: true,
value: 'randy'
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
可以看出 name 属性默认是一个可配置、可枚举、可写入的数据属性。
# 修改属性描述符
# 不可配置
// 将 name 属性设置为不可配置
Object.defineProperty(person, 'name', {
configurable: false
});
// 删除 name 属性
delete person.name
// 打印 name 属性,仍然存在
console.log(person.name); // randy
// 将 name 属性设置为可配置
// 此时会报错:不能重新定义 name 属性
Object.defineProperty(person, 'name', {
configurable: true
});
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
将一个属性设置为不可配置后,该属性不能被删除也不能再次修改属性相关的描述符。
# 不可枚举
// 打印 person 所有属性
console.log(Object.keys(person)); // ['name']
// 将 name 属性设置为不可枚举
Object.defineProperty(person, 'name', {
enumerable: false
});
// 打印 person 所有属性
console.log(Object.keys(person)); // []
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Object.keys() 返回一个由对象自身带有属性组成的数组。第一次返回的数组中带有 name,而第二次返回空数组。
# 不可写入
// 修改 name 的值
person.name = 'Tony';
console.log(person.name); // Tony
// 将 name 属性设置为不可写入
Object.defineProperty(person, 'name', {
writable: false
});
// 修改 name 的值
person.name = 'Randy';
console.log(person.name); // Tony
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
name 属性变为了只读属性
# 赋值操作
var person = {}
Object.defineProperty(person, 'name', {
value: 'randy'
});
console.log(person.name); // randy
1
2
3
4
5
2
3
4
5
# 访问器属性
var num = 0;
Object.defineProperty(person, 'age', {
get: function() {
console.log('调用 age 属性的 getter 函数');
return num;
},
set: function(newVal) {
num = newVal;
console.log('调用 age 属性的 setter 函数');
}
});
person.age = 99; // 打印:调用 age 属性的 setter 函数
console.log(person.age); // 打印:调用 age 属性的 getter 函数
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
设置 age 属性的值会调用其 set 方法。
获取 age 属性的值会调用其 get 方法。