前言
很多学习过vue的同学,在学习vue响应式数据(或者双向绑定)的原理时,都接触过get,set,Object.defineProperty这句个函数,并且大概知道它们的用法。但是一提到属性描述符,大家就很陌生了。今天详细的给大家讲解一下什么事属性描述符。
let person = {
firstName: "蔡",
lastName: "徐坤",
get fullName() {
return this.firstName + " " + this.lastName;
},
set fullName(name) {
let parts = name.split(" ");
this.firstName = parts[0];
this.lastName = parts[1];
},
};
console.log(person.fullName);
person.fullName = "周 杰伦";
console.log(person.fullName);
首先,属性描述符一共有6种
- value:设置属性值,默认值为 undefined。
- writable:设置属性值是否能被修改,默认值为 true。
- enumerable:设置属性是否可枚举.比如,是否允许使用 for/in 语句遍历访问,默认为 true。
- configurable:设置是否可设置属性特性,默认为 true。如果为 false,你将无法修改或者删除该属性的值。
- get:取值函数,当访问该属性时,该方法会被执行,默认为 undefined。
- set:存值函数,当属性值修改时,触发执行该方法,默认为 undefined。
当一个属性描述符没有没有get和set时,它是个数据描述符。当它没有value和writable时,它是个存取描述符。如果一个描述符同时有(value或writable)和(get或set)关键字,将会产生一个异常。
configurable | enumerable | value | writable | get | set | |
---|---|---|---|---|---|---|
数据描述符 | 可以 | 可以 | 可以 | 可以 | 不可以 | 不可以 |
存取描述符 | 可以 | 可以 | 不可以 | 不可以 | 可以 | 可以 |
示例1:
下面示例演示了使用 value 读写属性值的基本用法。
var obj = {}; //定义空对象
Object.defineProperty(obj, "age", { value: 18 });
console.log(obj.age);
console.log(Object.getOwnPropertyDescriptor(obj, "age").value); //返回18
示例2:
下面示例演示了使用 writable 属性禁止修改属性 age。在正常模式下,如果 writable 为 false,重写属性值不会报错,但是操作失败,而在严格模式下则会抛出异常。
var obj = {}; //定义空对象
Object.defineProperty(obj, "age", {
value: 18,
writable: false, //禁止修改属性值
});
obj.age = 28; //由于禁止修改,此时修改失败
console.log(obj.age); //结果仍然是18
console.log(Object.getOwnPropertyDescriptor(obj, "age").value); //返回18
示例3
configurable 可以禁止修改属性描述符,当其值为 false 时,value、writable、enumerable 和 configurable 禁止修改,同时禁止删除属性。
在下面示例中,当设置属性 age 禁止修改配置后,下面操作都是不允许的。
var obj = {}; //定义空对象
var obj = Object.defineProperty({}, "age", {
writable: true,
configurable: false, // 禁止配置(换而言之,无法修改属性描述符)
});
obj.age = 28;
console.log(obj.age); //undefined
console.log(Object.getOwnPropertyDescriptor(obj, "age").value); //undefined
Object.defineProperty(obj, "age", { value: 2 }); //抛出异常
Object.defineProperty(obj, "age", { writable: true }); //抛出异常
Object.defineProperty(obj, "age", { enumerable: true }); //抛出异常
Object.defineProperty(obj, "age", { configurable: true }); //抛出异常
get和set
通常,我们使用点来访问属性
let obj = {};
obj.age = 28;
console.log(obj.age);
除了点之外,属性描述符给我们提供了2个函数,也可以访问对象的属性。set( ) 函数可以设置 value 属性值,而 get( ) 函数可以读取 value 属性值。虽然看起来点访问更轻松,但是属性描述符提供了一些更高级的功能,如禁用部分特性、设计访问条件、利用内部变量或属性进行数据处理等。
正常写法:
var obj = Object.create(Object.prototype, {
_age: {
value: 18,
writable: true,
},
age: {
get: function () {
return this._age;
},
set: function (value) {
this._age = value;
},
},
});
console.log(obj.age);
obj.age = "28";
简要写法:
注意: get( ) 函数不能接收参数, set( ) 函数只能接收一个参数,用于设置属性的值。
var obj = {
_age: 18,
get age() {
return this._age;
},
set age(value) {
this._age = value;
},
};
console.log(obj.age);
obj.age = 28;
console.log(obj.age);