Object— Object.defineProperty()(详解、原理、作用、使用场景、使用方式)

一.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:设置属性值的函数。
 1 let obj= {
 2  age : '18'
 3 }
 4 Object.defineProperty(obj,'name',{
 5     value : 'red'
 6 })
 7 Object.defineProperty(obj,'age',{
 8     value : '20'
 9 })
10 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 是一个包含属性特性的对象,可以包括 valuewritableenumerableconfigurableget 和 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() 方法还可以用于定义属性访问器。属性访问器是一种特殊的属性,可以通过 getset 方法来获取和设置属性的值。属性访问器提供了更灵活的属性操作方式,可以实现对属性值进行计算、验证等操作。

综上所述,Object.defineProperty() 方法是一个非常强大和灵活的对象操作工具,可以用于定义新属性、修改现有属性、精确控制属性特性和实现属性访问器等多种目的。在实际开发中,开发人员经常会使用 Object.defineProperty() 方法来实现数据模型层的功能、界面控件的视图绑定等。

四.Object.defineProperty()使用场景

1.数据模型定义:在前端开发中,可以使用 Object.defineProperty() 来定义数据模型的属性。这样可以精确地控制属性的特性,例如是否可写、是否可枚举等,从而确保数据模型的正确性和安全性。

2.属性访问控制:通过 Object.defineProperty() 方法,可以定义属性访问器,使用 getset 方法控制属性的读取和赋值过程。这种方式可以实现对属性值进行计算、验证、转换等操作,增强了属性访问的灵活性。

3.界面绑定:在一些前端框架中,如 Vue.js、React 等,可以利用 Object.defineProperty() 来实现属性变化的监听和界面数据的自动更新。通过定义属性访问器,在属性值发生变化时自动触发界面的更新,实现数据驱动视图的效果。

4.对象扩展:在某些情况下,需要向现有对象中添加新的属性,并控制这些属性的特性。Object.defineProperty() 可以用来为现有对象动态添加新的属性,并设置属性的特性。

5.库和框架开发:在编写库或框架时,可能需要对外暴露的接口进行控制,以确保接口的正确使用和防止误操作。Object.defineProperty() 可以用来定义接口的特性,限制接口的可写性、可配置性等。

五.Object.defineProperty()使用方式

 1 // (1)定义新属性
 2 let obj= {
 3  age : '18'
 4 }
 5 Object.defineProperty(obj,'name',{
 6     value : 'red'
 7 })
 8 console.log(obj) //{age: '18', name: 'red'}
 9 
10 // (2)修改已有属性
11 Object.defineProperty(obj,'age',{
12     value : '20'
13 })
14 console.log(obj) //{age: '20', name: 'red'}
15 
16 Object.defineProperty(obj,'age',{
17     writable: false
18 })
19 obj.age = '33'
20 console.log(obj) //{age: '20', name: 'red'}
21 
22 // (3)定义属性访问器
23 let object = {
24     age : '10',
25     get(value){
26         console.log(`get:${this.age}`)
27         return this.age
28     },
29     set(newValue){
30         this.age = newValue
31         console.log(`set:${newValue}`)
32 
33     }
34 
35 }
36 object.age = '20'
37 console.log(object.get())
38 object.set('30')
39 
40 // (4)批量定义多个属性
41 let obj1 = {}
42 
43 Object.defineProperties(obj1, {
44   name: { value: 'red', writable: false },
45   age: { value: '15', writable: true }
46 });
47 
48 console.log()
49 console.log(obj1) //{name: 'red', age: '15'}
50 
51 // (5)冻结对象(禁止添加新属性、删除属性、修改属性)
52 const obj2 = { name: 'red' };
53 Object.defineProperty(obj2, 'name', { writable: false ,configurable:false}); 
54 Object.preventExtensions(obj2); //无法再添加新属性
55 console.log(obj2)
56 delete obj2.name; //删除属性
57 obj2.age = '19'; //修改属性
58 console.log(obj2.name); // red
59 console.log(obj2.age); // undefined
60 
61 // (6)监听对象中某个参数改变
62 function watch(obj, propName) {
63   let value = obj[propName];
64   Object.defineProperty(obj, propName, {
65     get() {
66       console.log(`获取 ${propName}: ${value}`);
67       return value;
68     },
69     set(newValue) {
70       console.log(`设置 ${propName} 为 ${newValue}`);
71       value = newValue;
72     }
73   });
74   return obj;
75 }

 

posted on 2024-02-22 23:01  萬事順意  阅读(1963)  评论(0编辑  收藏  举报