defineProperty的属性
Object.defineProperty定义新属性或修改原有的属性
Object.defineProperty(obj, prop, descriptor)
参数说明:
obj:必需。目标对象
prop:必需。需定义或修改的属性的名字
descriptor:必需。目标属性所拥有的特性
descriptor里面的属性都是可选的,每一个属性的作用如下,具体的使用方法详见官方文档,这里只是大致罗列出来个属性
- value 该属性对应的值,可以是任意类型的值,默认为undefined
- writeable 该属性的值是否可以被重写 默认是false不能被重写
- enumberable 该属性是否可以被枚举(使用for...in 或者Object.keys()能遍历出来)默认是false 不可被枚举
- configurable 是否可以删除目标属性或是否可以再次修改属性的特性(writable, configurable, enumerable)。设置为true可以被删除或可以重新设置特性;设置为false,不能被可以被删除或不可以重新设置特性。默认为false。
这个属性起到两个作用:目标属性是否可以使用delete删除 目标属性是否可以再次设置特性
第5个属性就是存取器(注意:当使用了getter或setter方法,不允许使用writable和value这两个属性)
相信用过vue的同学,对vue的数据双向绑定的原理有一定的了解,那就是数据劫持,就是用的Object.defineProperty这个方法,里面定义了setter和getter方法,通过观察者模式(发布订阅模式)来监听数据的变化,从而做相应的逻辑处理。
let obj = {}
let initVal = 123
Object.defineProperty(obj, 'age', {
set: function(val) {
console.log("改变")
initVal = val
},
get: function() {
return initVal
}
})
console.log(obj.age) // 执行get 方法 输出123
obj.age = 456 // 执行set 方法 输出改变 这时的initVal 赋值为456
console.log(obj.age) // 输出456
这里就具体讲解vue数据双向绑定的原理了,这里分享一个通过defineProperty解决异步状态判断的问题。在实际项目中H5与原生APP的交互还是很多,这里我们定下的协议就是 调用原生的方法的时候,必须先调用ready初始化方法,只有调用ready成功后,才能调用后续的方法,后续的方法这里用getUserInfo方法作为例子
// 正常采用promise的处理
function Ready(){
retrun new Promise((resolve,reject)=>{
// 原生的ready 方法
function ready(){
resolve()
}
ready()
})
}
Ready().then(()=>{
getUserInfo()
})
但是实际情况的话,加上jsBridge,会显得很复杂,实现起来也不是很简单 考虑的就是定义一个全局变量stats 设置为false,在ready放法中改变state的值,触发set 方法 通过判断来执行 resolve,
let _resolve = null; // 用来将promise的resovle 保存 延迟将Promise对象的状态从“未完成”变为“成功”
let promise = new Promise(resolve => {_resolve=resolve})
let obj = {}
let _state = false
Object.defineProperty(obj, 'state', {
set: function(val) {
!state && val && _resolve ()
_state = val
},
get: function() {
return _state
}
})
// 这里的then方法不会立马被调用 因为没有执行resovle
promise.then(()=>{
getUserInfo()
})
// 模拟异步调用 原生的方法
setTimeOut(()=>{
obj.state = true
},1000)
这只是一个简答的例子,实际运用的时候会有点出入,掌握这个思想最为重要,其次对promise的理解要深刻。