一.Object.defineProperty()详解
Object.defineProperty() 是 JavaScript 中用于定义或修改对象的属性的方法,可以控制属性的特性(如可枚举性、可配置性、可写性等)。
Object.defineProperty() 方法的语法如下:
Object.defineProperty(obj, prop, descriptor) // obj:要在其上定义属性的对象。 // prop:要定义或修改的属性的名称。 // descriptor:属性的描述符对象,包含属性的特性设置。 // descriptor 对象包含以下属性: // configurable:属性是否可配置,默认为 false。 // enumerable:属性是否可枚举,默认为 false。 // value:属性的值,默认为 undefined。 // writable:属性是否可写,默认为 false。 // get:获取属性值的函数。 // set:设置属性值的函数。 let obj= { age : '18' } Object.defineProperty(obj,'name',{ value : 'red' }) Object.defineProperty(obj,'age',{ value : '20' }) console.log(obj) //{age: '20', name: 'red'}
Object.defineProperty() 方法可以用来定义新属性或修改已有属性的特性。如果属性已经存在,Object.defineProperty() 方法将会更新属性的特性;如果属性不存在,Object.defineProperty() 方法将会创建一个新的属性。
需要注意的是,使用 Object.defineProperty() 方法定义的属性默认情况下是不可配置的,这意味着不能使用 delete 关键字删除这些属性。如果需要定义可配置的属性,可以在 descriptor 对象中将 configurable 属性设置为 true。
二.Object.defineProperty()工作原理
1.首先,检查传入的参数是否为对象。如果不是对象,则抛出 TypeError。
2.接着,创建或修改指定对象的属性,需要传入三个参数:目标对象 obj、属性名 prop 和属性描述符 descriptor。
3.属性描述符 descriptor 是一个包含属性特性的对象,可以包括 value、writable、enumerable、configurable、get 和 set 等属性。
4.根据属性描述符中的设置,对属性进行定义或修改。例如,可以设置属性的值、可写性、可枚举性和可配置性等。
5.创建或修改属性后,返回目标对象。
在对属性进行定义或修改时,Object.defineProperty() 方法会根据属性描述符中的设置对属性进行相应的处理。例如,如果将 writable 设置为 false,则属性将变为只读;如果将 enumerable 设置为 true,则属性将变为可枚举。
三.Object.defineProperty()作用
1.定义新属性:可以使用 Object.defineProperty() 方法在对象上定义新的属性。通过设置 value 属性,可以为新属性赋初始值;通过设置 writable 属性,可以指定新属性是否可写;通过设置 enumerable 属性,可以指定新属性是否可枚举;通过设置 configurable 属性,可以指定新属性是否可配置。
2.修改已有属性:如果对象上已经存在一个属性,可以使用 Object.defineProperty() 方法修改该属性的特性。例如,可以将现有属性的可写性修改为只读,或将现有属性的可枚举性修改为不可枚举等。
3.精确控制属性特性:通过 Object.defineProperty() 方法,开发人员可以精确地控制属性的特性,例如可写性、可枚举性、可配置性等。这些特性对于确保代码的正确性和安全性非常重要。
4.实现属性访问器(accessor):除了可以定义普通属性之外,Object.defineProperty() 方法还可以用于定义属性访问器。属性访问器是一种特殊的属性,可以通过 get 和 set 方法来获取和设置属性的值。属性访问器提供了更灵活的属性操作方式,可以实现对属性值进行计算、验证等操作。
综上所述,Object.defineProperty() 方法是一个非常强大和灵活的对象操作工具,可以用于定义新属性、修改现有属性、精确控制属性特性和实现属性访问器等多种目的。在实际开发中,开发人员经常会使用 Object.defineProperty() 方法来实现数据模型层的功能、界面控件的视图绑定等。
四.Object.defineProperty()使用场景
1.数据模型定义:在前端开发中,可以使用 Object.defineProperty() 来定义数据模型的属性。这样可以精确地控制属性的特性,例如是否可写、是否可枚举等,从而确保数据模型的正确性和安全性。
2.属性访问控制:通过 Object.defineProperty() 方法,可以定义属性访问器,使用 get 和 set 方法控制属性的读取和赋值过程。这种方式可以实现对属性值进行计算、验证、转换等操作,增强了属性访问的灵活性。
3.界面绑定:在一些前端框架中,如 Vue.js、React 等,可以利用 Object.defineProperty() 来实现属性变化的监听和界面数据的自动更新。通过定义属性访问器,在属性值发生变化时自动触发界面的更新,实现数据驱动视图的效果。
4.对象扩展:在某些情况下,需要向现有对象中添加新的属性,并控制这些属性的特性。Object.defineProperty() 可以用来为现有对象动态添加新的属性,并设置属性的特性。
5.库和框架开发:在编写库或框架时,可能需要对外暴露的接口进行控制,以确保接口的正确使用和防止误操作。Object.defineProperty() 可以用来定义接口的特性,限制接口的可写性、可配置性等。
五.Object.defineProperty()使用方式
// (1)定义新属性 let obj= { age : '18' } Object.defineProperty(obj,'name',{ value : 'red' }) console.log(obj) //{age: '18', name: 'red'} // (2)修改已有属性 Object.defineProperty(obj,'age',{ value : '20' }) console.log(obj) //{age: '20', name: 'red'} Object.defineProperty(obj,'age',{ writable: false }) obj.age = '33' console.log(obj) //{age: '20', name: 'red'} // (3)定义属性访问器 let object = { age : '10', get(value){ console.log(`get:${this.age}`) return this.age }, set(newValue){ this.age = newValue console.log(`set:${newValue}`) } } object.age = '20' console.log(object.get()) object.set('30') // (4)批量定义多个属性 let obj1 = {} Object.defineProperties(obj1, { name: { value: 'red', writable: false }, age: { value: '15', writable: true } }); console.log(obj1) //{name: 'red', age: '15'} // (5)冻结对象(禁止添加新属性、删除属性、修改属性) const obj2 = { name: 'red' }; Object.defineProperty(obj2, 'name', { writable: false ,configurable:false}); Object.preventExtensions(obj2); //无法再添加新属性 console.log(obj2) delete obj2.name; //删除属性 obj2.age = '19'; //修改属性 console.log(obj2.name); // red console.log(obj2.age); // undefined // (6)监听对象中某个参数改变 function watch(obj, propName) { let value = obj[propName]; Object.defineProperty(obj, propName, { get() { console.log(`获取 ${propName}: ${value}`); return value; }, set(newValue) { console.log(`设置 ${propName} 为 ${newValue}`); value = newValue; } }); return obj; }