Object函数的内置方法 Object.defineProperty
一、定义
Object.defineProperty()方法用于在对象上定义或修改一个自有属性,并返回这个对象。
二、语法
Object.defineProperty(obj, prop, descriptor)
参数:
obj:要定义或修改属性的对象
prop:属性字符串名
descriptor:属性描述符对象
返回值:
被传递给函数的对象
三、属性描述符
对象的属性的属性描述符主要有两种形式,分别是数据描述符和存取描述符。
数据描述符是一个具有值的属性。
存取描述符是由getter和setter函数描述的属性。
数据描述符具有的键值:
configurable:可配置性。当该特性为true时,属性描述符可以被修改,属性可以被删除。默认为false。
enumerable:可枚举性。当该特性为true时,属性可以出现在对象的枚举属性中。默认为false。
writable:可写性。当该特性为true时,属性的值可以被赋值运算符改变。默认为false。
value:属性对应的值。可以是任意有效的JavaScript值。默认为undefined。
存取描述符具有的键值:
configurable:可配置性。当该特性为true时,属性描述符可以被修改,属性可以被删除。默认为false。
enumerable:可枚举性。当该特性为true时,属性可以出现在对象的枚举属性中。默认为false。
get:一个给属性提供getter的方法。如果没有getter则默认为undefined,属性将不可读。
set:一个给属性提供setter的方法。如果没有setter则默认为undefined,属性将不可以修改。
如果一个属性描述符不具有value、writable、set和get的任意一个关键字,则认为是一个数据描述符。
四、示例
示例1:定义一个数据属性
var obj = Object.defineProperty({}, 'a', {
value: 1
});
Object.getOwnPropertyDescriptor(obj, 'a');
// {value: 1, writable: false, enumerable: false, configurable: false}
obj.b = 2;
Object.getOwnPropertyDescriptor(obj, 'b');
// {value: 2, writable: true, enumerable: true, configurable: true}
通过Object.defineProperty()方法定义的数据属性,如果没有指定writable、enumerable、configurable特性,则这三个特性默认为false。
通过表达式直接创建的属性(b),默认是数据属性,且writable、enumerable、configurable特性,则这三个特性默认为true。
示例2:定义一个存取属性
var obj = { x: 1 };
Object.defineProperty(obj, 'a', {
get: function () { return this.x;},
set: function (val) { this.x = val;}
});
Object.getOwnPropertyDescriptor(obj, 'a');
// {get: ƒ, set: ƒ, enumerable: false, configurable: false}
通过Object.defineProperty()方法定义的存取属性,如果没有指定enumerable、configurable特性,则这两个特性默认为false。
示例3:数据属性的特性功能示例
// 创建一个空对象
var obj = {};
// 定义一个可写的、不可枚举的、可配置的属性x
Object.defineProperty(obj, 'x', {
value: 1,
writable: true,
enumerable: false,
configurable: true
});
// 访问对象的属性
obj.x; // 1,说明属性是存在的
// 枚举对象的属性,获取不到属性x
Object.keys(obj); // []
// 修改属性的可写性,使其变为只读
Object.defineProperty(obj, 'x', { writable: false });
// 尝试修改属性的值
obj.x = 2;
obj.x; // 1, 静默修改失败,在严格模式下引发TypeError异常。
// 目前属性是可配置的,故可以通过defineProperty来修改属性的值
Object.defineProperty(obj, 'x', { value: 2 });
obj.x; // 2 属性值修改成功
// 将属性可写性改回可写
Object.defineProperty(obj, 'x', { writable: true });
// 将属性可配置性改成不可配置
Object.defineProperty(obj, 'x', { configurable: false });
// 此时,可以修改对象属性的值,但不能修改对象属性的可枚举性和可配置性,强行修改会引发TypeError
// 但此时,依然可以把对象属性的可写性改回不可写
Object.defineProperty(obj, 'x', { writable: false });
// 自从之后,对象的属性x,不可配置、不可修改、不可枚举、不可删除。
如果configurable为false,不可修改enumerable和configurable,但可以把writable从true改为false,无法把writable从false改为true。
如果configurable为true,writable为false,只能通过Object.defineProperty()方法来修改属性的值。
示例4:存取属性的特性功能演示
var obj = {};
obj.a = 1;
obj.b = 2;
Object.defineProperty(obj, 'c', {
get: function () {
return Math.sqrt(obj.a * obj.a + obj.b * obj.b);
},
set: function (value) {
obj.a = value;
}
});
Object.getOwnPropertyDescriptor(obj, 'c');
// {get: ƒ, set: ƒ, enumerable: false, configurable: false}
// 由于在定义属性c的时候没有显式指定enumerable和configurable的值,故这2个特性默认为false。
// 此时不能修改其getter和setter方法。
// 尝试修改为数据属性
Object.defineProperty(obj, 'c', { value: 3 });
// 上述操作会引发TypeError:Cannot redefine property: c
如果存取属性是不可配置的,则不能修改其getter和setter方法,也不能将其转换为数据属性。
示例5:数据属性和存取属性的转换
var obj = {};
// 定义一个可写、可配置、可枚举的数据属性
Object.defineProperty(obj, 'a', {
value: 1,
writable: true,
enumerable: true,
configurable: true
});
Object.getOwnPropertyDescriptor(obj, 'a');
// {value: 1, writable: true, enumerable: true, configurable: true}
obj.a; // 1
// 转换为存取属性
Object.defineProperty(obj, 'a', {
get: function () {
console.log('get a');
return 2;
}
});
Object.getOwnPropertyDescriptor(obj, 'a');
// {get: ƒ, set: undefined, enumerable: true, configurable: true}
obj.a; // 'get a', 2
// 再转回数据属性
Object.defineProperty(obj, 'a', {
value: 3
});
obj.a; // 3
如果属性是可配置的,则可以从数据属性转为存取属性,也可以从存取属性转为数据属性。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!