对象属性描述对象-JavaScript
2024-10-10 23:15:44一、定义
属性描述对象是 ECMAScript 5 新增的语法,它其实就是一个内部对象,用来描述对象的属性的特性。每个属性都有自己对应的属性描述对象,用来描述该属性的信息,以及控制它的行为。
属性描述对象提供6个属性描述:
1. value
表示属性的值,默认为undefined,可以是任何类型值。
2. writable
boolean类型,表示该属性值是否可以被修改,默认是true,如果是false,表示不能修改属性值。
3. enumerable
enumerable是一个布尔值类型,表示该属性是否可以被遍历,默认是true。如果是false,会使某些操作(比如for in 、Object.keys)跳过遍历。
4. configurable
configurable是一个布尔值,表示可配置性,默认为true。其为true时,表示该属性可以被删除,也可以修改属性描述对象。如果为false,表示不能删除该属性,也不得改变该属性的属性描述对象。
5. get
是一个函数,用于获取属性的值。当访问该属性时,会调用该函数并返回其返回值。默认是undefined。
6. set
是一个函数,用于设置属性的值。当访问该属性时,会调用该函数并返回其返回值。默认是undefined。
二、示例
1. value
表示属性值,通过这个属性,可以获取和设置属性的值。
const obj = {};
obj.name = "xiaoming";
Object.getOwnPropertyDescriptor(obj, "name").value; // xiaoming
Object.defineProperty(obj, "name", { value: "xiaoli" }); // {name: “xiaoli”}
obj.name // xiaoli
2. writable
该属性是一个布尔值类型,表示是否可以修改属性值。
const obj = {};
obj.name = "xiaoming";
Object.getOwnPropertyDescriptor(obj, "name").value; // xiaoming
Object.defineProperty(obj, "name", { writable: false }); // {name: “xiaoming”}
obj.name = "xiaoli"; // 修改name值
obj.name; // xiaoming 返回的name值还是之前的,并不是最新赋值的
需注意,在正常模式下,直接目标属性赋值(obj.name = "xiaoli"),对writable为false(configurable是否为false、true无关)的属性赋值不会报错,只会默默失败。但是,严格模式下会报错,即使对name属性重新赋予一个同样的值。
"use strict";
const obj = {};
obj.name = "xiaoming";
Object.getOwnPropertyDescriptor(obj, "name").value; // xiaoming
Object.defineProperty(obj, "name", { writable: false }); // {name: “xiaoming”}
obj.name = "xiaoming";
// TypeError: Cannot assign to read only property “name” of object
3. enumerable
该属性是一个布尔值类型,表示是否可以通过for in 或者 Object.keys()进行遍历,如果是false,遍历时,跳过该属性。
const obj = {};
obj.name = "xiaoming";
obj.age = 18;
Object.getOwnPropertyDescriptor(obj, "name").enumerable; // true 可枚举
for(let key in obj) {
console.log(key); // name age
}
// 设置enumerable为false
Object.defineProperty(obj, "name", { enumerable: false });
Object.getOwnPropertyDescriptor(obj, "name").enumerable; // false 不可枚举
for(let key in obj) {
console.log(key); // age
}
4. configurable
该属性是一个布尔值类型,表示可配置性,有两方面作用:
- 是否可修改属性描述对象
- 是否可删除目标属性
(1)是否可修改属性描述对象
如果configurable为false,value、enumerable、writable和configurable禁止修改,但需要注意的有两点:
- 当configurable为false时,writable为false时,其值修改为true会报错,但是如果writable为true时,其值修改为false是允许的。
- 对于value,只要writable和configurable有一个为true,就允许改动。
如果configurable为false,value、enumerable、writable和configurable修改值时,会报错:
const obj = Object.defineProperty({}, "name", {
value: "xiaoming",
writable: false,
enumerable: false,
configurable: false
});
Object.defineProperty(obj, "name", { value: "xiaoli" });
// TypeError: Cannot redefine property: name
Object.defineProperty(obj, "name", { writable: true });
// TypeError: Cannot redefine property: name
Object.defineProperty(obj, "name", { enumerable: true });
// TypeError: Cannot redefine property: name
Object.defineProperty(obj, "name", { configurable: true });
// TypeError: Cannot redefine property: name
但是如果你设置的值和当前属性描述对象的值一致时,并不会报错。
const obj = Object.defineProperty({}, "name", {
value: "xiaoming",
writable: false,
enumerable: false,
configurable: false
});
Object.defineProperty(obj, "name", { configurable: false });
Object.defineProperty(obj, "name", { value: "xiaoming" });
Object.defineProperty(obj, "name", { writable: false });
Object.defineProperty(obj, "name", { enumerable: false });
// 以上都不报错
当configurable为false时,writable为false时,其值修改为true会报错,但是如果writable为true时,其值修改为false是允许的。
const obj = Object.defineProperty({}, "name", {
value: "xiaoming",
writable: true,
enumerable: false,
configurable: false
});
Object.defineProperty(obj, "name", { writable: false }); // 修改成功
const obj2 = Object.defineProperty({}, "name", {
value: "xiaoming",
writable: false,
enumerable: false,
configurable: false
});
Object.defineProperty(obj2, "name", { writable: true });
// TypeError: Cannot redefine property: name
对于value,只要writable和configurable有一个为true,就可以修改。
var obj = Object.defineProperty({}, "name", {
value: "xiaoming",
writable: true,
configurable: false
});
Object.defineProperty(obj, "name" { value: "xiaoli" }); // 修改成功
obj.name; // xiaoli
var obj2 = Object.defineProperty({}, "name" {
value: "xiaoming",
writable: false,
configurable: true
});
Object.defineProperty(obj2, "name", { value: "xiaoli" }); // 修改成功
obj2.name; // xiaoli
(2)是否可删除目标属性
configurable为false,禁止删除属性,如果为true时,可以删除属性。
const obj = Object.defineProperties({}, {
name: {
value: "xiaoming",
configurable: true
},
age: {
value: 2,
configurable: false
}
});
delete obj.name // true,删除成功
obj.name // undefined
delete obj.age // false,删除失败,并不会报错
obj.age // 2
5. get 和set 函数
除了平时使用的点语法(obj.name)或者中括号语法(obj["name"])访问属性的 value 外,还可以使用访问器,包括 set 和 get 两个函数。
set 函数用来设置 value 值,get 函数用来读取 value 值。
举例说明一下:
const obj = Object.defineProperties({}, {
_name: {
value: "xiaoming",
writable: true
},
name: {
get() {
return this._name;
},
set(value) {
this._name = value;
}
}
});
obj.name; // xiaoming
obj.name = "xiaoli";
obj.name; // xiaoli
第一次执行obj.name的时候,调用name的属性描述对象中的get函数,返回_name,即miaoxing。
当执行obj.name = "xiaoli"时,调用name的属性描述对象中的set函数,将_name赋值xiaoli,即此时_name的值是xiaoli。
第二次执行obj.name的时候,调用name的属性描述对象中的get函数,返回_name,即miaoli。
因此,此时返回的是xiaoli。