Object.defineProperty() personal understanding
Object.defineProperty() is used to define the properties of the properties in the object. These properties belong to the internal value of the object, so they cannot be accessed directly in JS.
In ES5, there are two attributes, includingData attributeswithAccessor properties
Data attributes
The data attribute contains aData valueThe position where you can read and write values, the data attribute has 4 characteristics used to describe its behavior
- [[ Configurable ]] indicates whether you can delete the attribute, whether you can modify the characteristics of the attribute, whether you can change the attribute to an accessor attribute, when you define the attribute directly on the object, the default value is true
- [[ Enumerable ]] Is it possible to return the attribute through a loop? Attribute defined directly on the object, this attribute defaults to true
- [[ Writing ]] Is it possible to modify the value of the attribute. The attribute defined directly on the object, the default value of this attribute is true
- [[ Value ]] The data value of the attribute. When reading an attribute value, read from this location, and when writing a new attribute, save the new value in this location. The default value is undefined
Use Object.defineProperty() to modify the default properties of the property, accepting three parameters: the object where the property is located, the property name, and a descriptor object. The property of the descriptor object must be the above four properties and cannot have other properties. Set one or more of the values, you can modify the corresponding characteristic value
Example:
let obj = {
name: "lalala",
age: 15,
idol: 'CR7'
};
Object.defineProperty(obj , 'name' , {
writable: false, //不可被修改
enumerable: false, //不可被遍历
value: "Well"
})
console.log(obj.name) //Well
obj.name = 'Nigo' //严格模式下会报错,非严格模式没事
console.log(obj.name) //Well
Object.keys(obj).forEach(key => {
console.log(key); //age , idol 不包含name属性
})
The object.defineProperty() method can be called multiple times to modify the same property, but if the configurable is set to false for the first modification, it cannot be modified again, and an error will be reported
let obj = {
name: "lalala",
age: 15,
idol: 'CR7'
};
Object.defineProperty(obj , 'name' , {
//没有设置configurable:false是可以再次修改的
writable: false, //不可被修改
enumerable: false, //不可被遍历
value: "Well"
})
console.log(obj.name) //Well
obj.name = 'Nigo' //严格模式下会报错,非严格模式没事
console.log(obj.name) //Well
Object.keys(obj).forEach(key => {
console.log(key); //age , idol 不包含name属性
})
Object.defineProperty(obj , 'name' , {
writable: true, //该为true
enumerable: false, //不可被遍历
value: "Well"
})
obj.name = 'Nigo' //可以修改属性了
console.log(obj.name) //Nigo
let obj = {
name: "lalala",
age: 15,
idol: 'CR7'
};
Object.defineProperty(obj , 'name' , {
//没有设置configurable:false是可以再次修改的
configurable:false, //不可再次修改该属性的特性
writable: false, //不可被修改
enumerable: false, //不可被遍历
value: "Well"
})
console.log(obj.name) //Well
obj.name = 'Nigo' //严格模式下会报错,非严格模式没事
console.log(obj.name) //Well
Object.keys(obj).forEach(key => {
console.log(key); //age , idol 不包含name属性
})
Object.defineProperty(obj , 'name' , {
//这里直接报错
writable: true,
enumerable: false,
value: "Well"
})
Accessor properties
The accessor property does not contain data values, but contains a pair of getter and setter functions (not required)
In addition, when a property has get and set methods, it is an accessor property
getter function
Function called when reading accessor properties
setter function
When writing accessor properties, call the setter function and pass in the new value, the setter function determines how to process the data
Accessor properties cannot be defined directly, they must also be defined by Object.defineProperty()
const obj = {
name: 'Well',
_age: 22, //表示只有通过对象方法能访问到的属性
}
Object.defineProperty(obj , 'age' , {
configurable:true, //表示能否delete删除属性,能否修改属性的特性,能否将属性改为数据属性,默认false
enumerable: true, //能否被遍历到,默认false
get() {
console.log("获取age的值");
return this._age;
},
set(newV) {
console.log("写入新值");
this._age = newV; //可以通过setter函数改变对象中的其他属性值
}
});
obj.age = 24; //写入新值
console.log(obj.age); //获取age的值 24
obj.age = 26; //写入新值
console.log(obj.age); //获取age的值 26
console.log(obj._age) //26
The attribute name of the accessor cannot be the same as the original attribute name of the object, otherwise the stack will overflow due to the endless loop
Changes in the data in the monitoring object:
const obj = {
a: 1,
b: 2,
c: 3
}
Object.keys(obj).forEach(key=>{
let value = obj[key]
Object.defineProperty(obj,key,{
get(){
console.log(`获取${
key}的行为被我劫持了`)
return value
},
set(v){
console.log(`${
key}的改变被我劫持了`);
value = v;
}
})
})
console.log(obj.b); //获取b的行为被我劫持了 2
obj.c = 5; //c的改变被我劫持了
It is not necessary to define getter and setter at the same time
Only defining the setter means that it can only be written, not read. When reading a property without a getter, strict mode will report an error, and non-strict mode will return undefined
Only define the getter means you can only read, not write, try to write, an error will be reported in strict mode, and it will be ignored in non-strict mode
Define multiple attributes
Object.defineProperties(), this method receives two parameters, both of which are two objects, the first one is the object to add and modify properties
The attributes in the second object should correspond to the attributes added or modified in the first object
Example:
const people = {
_name: 'Nigo',
_age: 28
};
Object.defineProperties(people , {
_name: {
value: 'HaHa',
//可修改其他特性
},
name: {
//定义一个访问器属性
get() {
return this._name;
}
},
age: {
set(newV) {
this._age = newV
}
}
})
Read the properties of attributes
Object.getOwnPropertyDescriptor()
The object where the attributes of the two parameters are located and the name of the attribute to be read, the return value of this method is an object
If it is a data attribute, the returned object contains configurable, enumerable, writabele, value
If it is an accessor attribute, the returned object contains configurable, enumerable, get, and set
In JS, you can use the Object.getOwnPropertyDescriptor() method on any object