Detailed explanation of the Object.defineProperty() method to understand the data proxy of vue2

The first article of the holiday. Regarding basic knowledge points, I feel that I am still very weak.
Take advantage of the holiday to review it again

Object.defineProperty(), for this method, more of it stays during the interview. When the interviewer asks you the difference between vue2 and vue3, you can’t help but mention this method. The bottom layer of vue2 is Object.defineProperty(), vue3 Is a proxy object

By the way, let’s list the differences between the two:

1. Performance optimization: Vue 3 introduces a rewrite of the responsive system to make it more efficient. Vue 3 uses Proxy objects. Compared with Object.defineProperty in Vue 2, Proxy can better capture and track modifications to responsive data, providing better performance.

2. Smaller size: Vue 3 uses a modular development method and can import functional modules on demand, thereby reducing the overall size of the framework.

3. Composition API: Vue 3 introduces the Composition API, a new way of organizing code that allows developers to create reusable logic blocks through the logical combination API. Compared with the Options API in Vue 2, the Composition API is more flexible and composable, making the code easier to maintain and reuse.

4. Better TypeScript support: Vue 3 is more friendly to TypeScript. Through the ts-check directive and related type declarations, it can provide better type checking and code intelligent prompts.

5. Teleport component: The Teleport component was introduced in Vue 3, which can easily render components to other locations in the DOM. This is very useful when dealing with modal boxes, pop-up layers, etc.

6. Better recursive components: Vue 3 has improved support for recursive components and can better handle the updating and rendering of recursive components.

Now about the Object.defineProperty() method, let’s go a little deeper

Object.defineProperty is a built-in method of JavaScript that is used to define a new property on an object or modify the characteristics of an existing property.

The syntax is as follows:

Object.defineProperty(obj, prop, descriptor)

Parameter notes:

obj:要在其上定义属性的对象。
prop:要定义或修改的属性的名称。
descriptor:要定义或修改的属性的描述符对象,包含属性的各种特性。

A descriptor object (also called a configuration item) contains the following optional properties:

value:属性的值,默认为 undefined。
writable:属性的值是否可以被修改。默认为 false,即该属性是只读的。
enumerable:属性是否可枚举(是否出现在对象的枚举属性中)。默认为 false。
configurable:属性是否可以被删除或修改特性。默认为 false。
get:读取时内部调用的函数
set:写入时内部调用的函数

A property named "name" is defined on the obj object through the Object.defineProperty method. The initial value of this property is "John" and is writable, enumerable and configurable. Subsequent assignment operations to the attribute can modify the value of the attribute
. Example:

const obj = {
    
    };

// 定义一个名为 "name" 的可写属性
Object.defineProperty(obj, 'name', {
    
    
  value: 'John',
  writable: true,
  enumerable: true,
  configurable: true
});

console.log(obj.name); // 输出 "John"

obj.name = 'Tom';
console.log(obj.name); // 输出 "Tom"

Directly use set (modify), get (get)

const obj = {
    
    
  _name: 'John',
  get name() {
    
    
    return this._name;
  },
  set name(value) {
    
    
    this._name = value;
  }
};

console.log(obj.name); // 输出 "John"

obj.name = 'Tom';
console.log(obj.name); // 输出 "Tom"

Still feeling a little unclear? Let’s put it in plain language:

If there is already an object

let person = {
    
    
name:'莲花',
gender:'男',
}

Now we need to add an attribute age with a value of 38

You can add it directly to the object

let person = {
    
    
name:'莲花',
gender:'男',
age:38
}

If in the actual work scenario, the property to be added is unknown and is added dynamically according to certain conditions, then adding it directly is definitely not appropriate. There is still a
difference between adding it directly and using Object.defineProperty() to add it. You can add it directly. You can change it at will, delete it at will, and be enumerated at will. What Object.defineProperty() adds can control whether it is allowed to be changed, whether it is allowed to be deleted, and whether it is allowed to be enumerated.

Example:

let person = {
    
    
name:'莲花',
gender:'男',
}
Object.defineProperty(person,'age',{
    
    
value:38,

})
//参数1:要添加参数的对象,给person对象添加,所以是person
//参数2,要添加的属性名,age
//参数3,配置项

Print to see the difference between adding directly and adding with Object.defineProperty().
Insert image description here
Add directly. The color of all property names is the same. However, when created by Object.defineProperty(), the color of age property name is lighter than the other two property names. , this is because the enumerable property of the Object.defineProperty() configuration item is false by default, that is, it cannot be enumerated by default and does not participate in traversal.
If we console.log(Object.keys(person)) and print an array composed of all property names of the person object, we will find that the property names added directly can be printed, while those created by Object.defineProperty() do not have age.

Insert image description here
If you want to be enumerated, set enumerable to true

let person = {
    
    
name:'莲花',
gender:'男',
}
Object.defineProperty(person,'age',{
    
    
value:38,
enumerable:true,//控制属性是否可以被枚举,默认为false
})

If we want to modify the value of age, we can add it directly and modify it through person.value. However, the value created by Object.defineProperty() cannot be modified directly. This involves the writable attribute. The default is false, which means it is not allowed by default. Modify and set it to true

let person = {
    
    
name:'莲花',
gender:'男',
}
Object.defineProperty(person,'age',{
    
    
value:38,
enumerable:true,//控制属性是否可以被枚举,默认为false
writable:true,//控制属性是否可以被修改,默认为false
})

If we don’t want the age attribute and want to delete it, we can add it directly by deleting person.age. However, the one created by Object.defineProperty() cannot be modified directly. This requires the configurable attribute, which defaults to false. , that is, deletion is not allowed by default, just set it to true

let person = {
    
    
name:'莲花',
gender:'男',
}
Object.defineProperty(person,'age',{
    
    
value:38,
enumerable:true,//控制属性是否可以被枚举,默认为false
writable:true,//控制属性是否可以被修改,默认为false
configurable:true,//控制属性是否可以被删除,默认为false
})

If there is a number field now, the requirement is that the value of age needs to read the value of number, that is, dynamic assignment.

Add directly:

let number = 18
let person = {
    
    
name:'莲花',
gender:'男',
age:number
}

Written like this, the value of number is indeed assigned to age. However, if the value of number changes later, say it becomes 20, the value of age will not change accordingly and will remain the original 18.

Because when the statement is executed from top to bottom, the first definition has been completed. Changing the value of number in the future is only the number's own business. It is over after the first definition, and the value of the person object will not be changed again. Change.
If you modify it manually and reassign age, it will indeed change the value of age. However, if you want the value of age to change as soon as number changes, you need to use the Object.defineProperty() method // directly modify it manually and reassign age
. Assignment example:


let number = 18
let person = {
    
    
name:'莲花',
gender:'男',
age:number
}
number = 20
person.age = number

//Object.defineProperty() example:


Object.defineProperty(person,'age',{
    
    
//当读取person的age属性时,get(getter)函数就会被调用,且返回值是age的值
//get:function(){
    
    }
//return number
//})
//简写:
get(){
    
    
return number
}
//当修改person的age属性时,set(setter)函数就会被调用,且会收到修改的具体值
//打印value,当值改变的时候确实value接收到了,但是age并没有改变,这是因为person的age属性接收的是number的值
//set确实调用了,但是number变量的值没有改变,所以set中给number赋值
set(value){
    
    
number = value
}

At this time, if the value of number changes, get will be triggered, and age will directly get the value of number.

If person.age is modified directly, set will be triggered. The value of number will be modified first, and then get will be triggered. Age will get the value of number.

After understanding Object.defineProperty, now start to understand the data proxy

Data proxy:
Use one object to proxy the operation of attributes in another object, monitor changes in attributes, intercept the reading and writing of attributes, etc.

Example:

let obj = {
    
    
a:'1'
}

let obj2 = {
    
    
b:'2'
}
//obj2想访问obj.a,且可以修改obj.a的值
//给obj2新增属性a
//get中返回obj.a,即obj2新增的属性a拿的是obj.a的值
//set中修改,当obj2.a值发生改变的时候,再赋值给obj.a,再触发get,obj2.a再去拿obj.a的值
Object.defineProperty(obj2,'a',{
    
    
get(){
    
    
return obj.a
}
set(value){
    
    
obj.a= value
}

End of the first chapter~~~

Guess you like

Origin blog.csdn.net/weixin_49668076/article/details/133420814