只是按照我所理解的进行说明。
该方法运行更加精确控制对象的属性。
>>语法
Object.defineProperty(obj, attr, descriptor)
1: obj:要在其上定义属性的对象。
2: attr:要定义或修改的属性的名称。只能定义一个。
3: descriptor:将被定义或修改的属性描述符(具体看下面👇)。
要同时定义多个属性可使用 Object.defineProperties()
>>属性描述符
属性描述符分为: 数据描述符 和 存取描述符.
>>数据描述符,存取描述符 共有可选键值:
configurable: 当该属性为 true 时,该属性描述符才能够被改变,该属性也能够被删除。默认为 false。
若手动设置为false,那就再也无法修改任何描述符(除writable描述符要设置为false时)!
enumerable: 当该属性 为 true 时,该属性才能够出现在对象的枚举属性中(是否能在for...in, Object.keys()中被枚举)。默认为 false。
>>数据描述符 可选键值:
value: 该属性的值。 (可以是任何JS有效值)。 默认为undefined。
writable: 概述为true时,赋值运算符赋值才会成功。默认为false。
>>存取描述符 可选键值:
get: 在获取该属性的值时 调用的函数,该方法返回值作为属性的值。 默认为undefined。
set: 在修改该属性的值时 调用的函数(默认传入修改的值)。 默认为undefined。
注意
1: 在用Object.defineProperty()设置时,只能同时对一类型描述符进行设置。否则会报错。 测试:
let o = {};
Object.defineProperty(o, 'test', {
value:1, //数据描述符
get(){ // 存取描述符.
return '测试'
}
});//会报错,因为不能同时对 两种类型的描述符进行操作.
2: 正常创建属性。描述符都会被赋值,而不是默认值。
下面用这个方法——Object.getOwnPropertyDescriptor()
查询描述符信息。测试:
let o = {
test:1
}// 可能你会以为,描述符会被赋值为上面所写的默认值。
let info = Object.getOwnPropertyDescriptor(o,'test');
console.log(info)
/* 显示信息如下
* configurable:true
* enumerable:true
* value:1
* writable:true
*/
在正常创建属性时,描述符都会被赋值。 大概情况为:
configuraable, enumerable, writable, 赋值为true.
value为所赋的值.
3: 描述符会被赋值为默认值的情况
>>数据描述符 设置为默认值
let o = {} // 在使用↓方法时,没有写的描述符,会被赋值为默认值。
Object.defineProperty(o, 'test', {}); //默认设置数据描述符
let info = Object.getOwnPropertyDescriptor(o,'test'); //获取描述符信息
console.log(info)
/* 显示信息如下
* configurable:false
* enumerable:false
* value:undefined
* writable:false
*/
set, get方法应该还是正常返回值,修改值。
>>存取描述符 设置为默认值
let o = {};
Object.defineProperty(o, 'test', {
set(){} // 因为默认会设置数据描述符的默认值,所以设置下get, 让set为默认值。
})
let info = Object.getOwnPropertyDescriptor(o,'test');
console.log(info);
/* 显示信息如下
* configurable:false
* enumerable:false
* set:function set() //我手动设置的
* get:undefined //默认值
*/
重点:如果属性是通过此方法设置的,那么没有主动设置的描述符键值,它会被设置为,默认值(导致属性无法访问,无法修改)。
所以要记得在使用此方法定义属性时,给必要描述符键值进行设置,除非默认值符合你预期。
>>实践
简单写一个数据双向绑定.(不需要记忆,只是展示其功能)
function getAndSet(obj, attr, getFn, setFn){
let nowVal = obj[attr];
Object.defineProperty(obj, attr, {
configurable:true,
enumerable:true,
get(){
getFn(nowVal) // 在获取时调用的方法
//可以写DOM操作,使其在数据改变的时候,DOM相应改变
return nowVal
},
set(newVal){
setFn(newVal, nowVal) // 在修改时调用的方法
//可以写DOM操作,使其在数据改变的时候,DOM相应改变
nowVal = newVal;
return newVal
},
})
}
let o = {
test:1
};
getAndSet(o, 'test', function(nowVal){
console.log(`get方法! 值:${nowVal}`)
},function(newVal, nowVal){
console.log(`set方法! 新值:${newVal},原值:${nowVal}`)
})
o.test // get方法! 值:1
o.test = 4 // set方法! 新值:4,原值:1
当属性值是对象时,函数就没效果了。毕竟只是简单的实现,你可以让其的所有属性再次去调用此方法。
更加复杂,强大的实现,可以去学Vue框架。
以上是我所知的的东西,有任何错误,请在评论指出!
O(∩_∩)O谢谢你的观看~