You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
//使用任意一种方式定义一个对象varex1={attr1: "initial value of attr1",attr2: "initial value of attr2"};//针对其中一个属性“attr1”设置“观察者”watch(ex1,"attr1",function(){alert("attr1 changed!");});//当“attr1”修改的时候“观察者”函数会被调用ex1.attr1="other value";`</pre>
//使用任意一种方式定义一个对象varex1={attr1: "inicial value of attr1",attr2: "initial value of attr2"};//定义“attr1”属性的监听函数watch(ex1,"attr1",function(){//在此域中阻止监听器的调用WatchJS.noMore=true;ex1.attr2=ex1.attr1+" + 1";});//给另一个属性定义“监听函数”watch(ex1,"attr2",function(){alert("attr2 changes");});//attr1修改的时候,会修改attr2但不会触发attr2的“监听函数”ex1.attr1="other value to 1";
用麻雀虽小五脏俱全来描述Watch.js比较合适。“观察者”模式是我们在开发的时候经常需要用到的。使用Watch.js那么我们就可以实现在_“每当对象属性改变的时候,执行你的函数”_。虽然有很多其他的库可以实现相同的功能,但是Watch.js却可以不改变你平时书写代码的方式,并且实现属性改变的监听功能。
API
让我们来看看它的API:
try demo
Watch.js还提供了其他有用的api:监控多个属性、监控整个对象或移除整一个watch。你可能会想到循环调用,例如:
WatchJS.noMore = true
可以确保在此次监听函数的调用中,对属性的修改不会触发新的监听函数。接下来看看它是如何实现它们的!Object.defineProperty
Object.defineProperty
是ECMAScript 5标准提供的方法,它允许你在一个对象上定义一个新属性或是修改原有属性的描述符。这个方法接收一个属性描述符,并用它来初始化(或更新)一个属性。例如:defineProperty
的第三个参数是描述符,value
设置属性值,writable
表示属性是否可写(不会报错,只是写操作不生效),enumerable
表示属性是否可以通过for in
迭代获取,configurable
表示属性该属性的描述符无法再被定义,并且属性也无法被delete
。get
和set
分别定义属性的access方法,注意不可同时定义属性的accessor和value及writable参数。具体的方法描述参考MDN上的文档Watch.js利用了属性的accessor方法实现了对属性变化的监听,代码如下:
defineWatcher
函数是定义监听者的主要函数,它做了如下几件事情:降级处理
defineGetAndSet
是利用了defineProperty
来设置监听函数,如果不支持则会尝试如下方法:有些稍微旧版本的先进浏览器可以使用这个方法来设置accessor。如果浏览器还是不支持那么会fallback到设置定时器监控。如下:
这个降级处理是存在bug的,它无法正确处理属性设置之间的间隔。原因在于javascript的线程模型,以及
setInterval
不是立即能知道更新,有50ms的间隔时间。样例如下:上面的代码在支持
defineProperty
的浏览器中执行结果如下:在不支持的浏览器中执行结果如下:
可见
setInterval
的降级处理是异步的,而defineProperty
是同步的。这在一些情况下会导致严重的bug,而且难以调试。所以在真正使用的环境中需要注意!总结
抛开watch.js的bug不谈,它还是有很多可圈可点的地方。使用下来觉得watch.js的优点如下:
缺点如下:
The text was updated successfully, but these errors were encountered: