[JS] Object.defineproperty method

Preface

Normally, you can add properties and methods directly to the object, but Object.defineproperty() will be more powerful.

var stu = new Person
stu.name = "张三"  // 添加属性
stu.say = function(){
    
    }  // 添加方法

The function of Object.defineProperty() is to directly define a new property on an object or modify an existing property. It is also the responsive principle of vue2.

grammar

Object.defineProperty(obj, prop, desc)

parameter

  • obj : the current object whose properties need to be defined
  • prop : The property name that currently needs to be defined "String, Symbol type"
  • desc : 属性描述符, through which to limit the reading and writing behavior of attributes

属性描述符

  • value: Set the value of the attribute
  • writable: whether the value can be rewritten, the default value is false
  • set: method to set the value of the target attribute
  • get: method to obtain the value of the target attribute
  • enumerable: whether the target attribute can be enumerated (whether it can be traversed), the default value is false
  • configurable: whether the target attribute can be deleted or modified again , the default value is false

There are two types of attribute descriptors: "data descriptors" and "access descriptors".

Among them, value and writable are data descriptors, get and set are access descriptors, and configurable and enumerable are not restricted.

Data descriptor (value, writable):

value: attribute value
writable: whether the value can be modified, the default is false

let person = {
    
    
    name: "张三",
}

Object.defineProperty(person, 'age', {
    
    
    value: 18,      // 设置属性值
    writable:true,  // 是否可修改,默认为false
})

console.log(person.age) // 18
person.age = 20
console.log(person.age) // 20

If you do not write writable or writable:false, you will see that the printing on the console has not changed.
Insert image description here

Access descriptor (get, set):

get: When someone reads person's prop, the get function (getter) will be called, and the return value is the value of prop.
set: When someone modifies person's prop, the set function (setter) will be called, and the return value will be Modified specific value received

let person = {
    
    
    name: "张三",
}

let num = 18

Object.defineProperty(person, 'age', {
    
    
  get: function () {
    
    
    console.log('有人操作对象了');
    return num
  },
  set: function (value) {
    
    
    console.log('值被修改了,value:', value);
    num = value
  },
})

Read prop and trigger get function

person.age    // 触发get函数(getter)

Insert image description here
Modify prop and trigger the set function

person.age = 20   // 触发set函数(setter)

Insert image description here

同时定义数据描述符和存储描述符会报错

Insert image description here

Insert image description here

configurable and enumerable descriptors

These two attribute descriptors can be used with either "data descriptors" or "storage descriptors".

configurable descriptor

Indicates whether it can be "modified" or "delete" again 该属性的属性描述符, Boolean value (default is false).
When set to true, the attribute descriptor of the attribute can be modified again, and the attribute can also be deleted from the corresponding object.
Generally, when using Object.defineProperty, it should be set to true because these key values ​​need to be changed.

delete

When configurable is not set (false), it cannot be deleted.

let person = {
    
    
	name:"张三"
}

Object.defineProperty(person, 'age', {
    
    
  value: 23,
})
delete person.age
console.log(person.age) // 23

configurable: true, you can delete it

let person = {
    
    
	name:"张三"
}

Object.defineProperty(person, 'age', {
    
    
  value: 23,
  configurable: true,  // 是否可以被删除或修改
})
delete person.age
console.log(person.age) // undefined
修改

There are two ways to modify the attribute value, one is in the form of assignment object.prop = xxx, and the other is by defining the attribute again Object.defineProperty()and resetting the value for the same prop.

The " modification " mentioned here is different from the "data descriptor" writable: true mentioned above. It refers to whether the attribute value can be modified, but whether it can be passed 属性定义的方式修改描述符.

configurable is true and can be modified.
let person = {
    
    
	name:"张三"
}
Object.defineProperty(person, 'age', {
    
    
  value: 23,
  writable: false, // 这里为false只是禁止通过直接赋值的形式修改属性值
  configurable: true,  // 是否可以被删除或修改
})


// 通过属性定义的方式修改描述符value
Object.defineProperty(person, 'age', {
    
    
  value: 18 // 这里重新定义了属性值,因为 configurable 为 true,所以可以修改
})
console.log(person.age); // 18


// 通过赋值的形式修改值,由于writable为false,所以不可修改
person.age = 20
console.log(person.age); // 18 
On the contrary, when it is false, it cannot be modified twice.
let person = {
    
    
	name:"张三"
}
Object.defineProperty(person, 'age', {
    
    
  value: 23,
  writable: true,
  configurable: false,  // 是否可以被删除或修改
})

// 通过属性定义的方式修改描述符value
Object.defineProperty(person, 'age', {
    
    
  value: 18 // 这里重新定义了属性值,因为 configurable 为 true,所以可以修改
})
console.log(person.age); // 18


// 通过赋值的形式修改值,由于writable为true,所以可以修改
person.age = 20
console.log(person.age); // 20

Summarize

  1. When configurable: false, the current attribute cannot be deleted and the descriptor of the current attribute cannot be reconfigured.
  2. configurable: When true, the current attribute can be deleted and all descriptors of the current attribute can be configured.
  3. 不要混淆writable和configurable, writable refers to whether it can be passed, and configurable refers to whether the attribute value can be modified in the way of attribute definition.

enumerable descriptor

Indicates whether the attribute can be enumerated (traversed), Boolean value (default is false).

let person = {
    
    
	name:"张三"
}

Object.defineProperty(person, 'age', {
    
    
  value: 23,
})
console.log(person.age)  // 23

In the above code, even if the age attribute is set and the value of age can be obtained, the newly added age attribute is not found when printing person directly. The results are as follows:
Insert image description here
using for...in traversal or the Object.keys method cannot be read. New age attribute

for (let key in person) {
    
    
  console.log(key)  // name
}

console.log(Object.keys(person))  // ['name']

Insert image description here

If you want new properties to be traversed, set the enumerable descriptor to true.

let person = {
    
    
	name:"张三"
}

Object.defineProperty(person, 'age', {
    
    
  value: 23,
  enumerable: true,  // 是否可枚举(遍历)
})

console.log(person);
for (let key in person) {
    
    
  console.log(key) 
}
console.log(Object.keys(person));

It is found that the new attribute age attribute can be traversed
Insert image description here

注意

  • Data descriptor (value, writable) and access descriptor (get, set), 不允许同时使用otherwise an error will be reported, configurable and enumerable are not restricted.

  • get and set do not need to exist at the same time and can be configured separately.

Guess you like

Origin blog.csdn.net/owo_ovo/article/details/135226257