是否可以在不使用Proxy
和setInterval
的情况下收听属性更改?
对于常见对象,您可以使用下面的函数,但该函数适用于所有现有属性,但不适用于包装后可能添加的任何属性。
function wrap(obj) {
var target = {};
Object.keys(obj).forEach(function(key) {
target[key] = obj[key];
Object.defineProperty(obj, key, {
get: function() {
console.log("Get");
return target[key];
},
set: function(newValue) {
console.log("Set");
target[key] = newValue;
}
});
});
}
var obj = {
a: 2,
b: 3
};
wrap(obj);
obj.a; // Get
obj.a = 2; // Set
obj.b; // Get
obj.b = 2; // Set
obj.c = 2; // Nothing
obj.c; // Nothing
如果对象是数组,则还可以监听length
属性,并在更改后重置所有get
和set
函数。这显然不是很有效,因为每当添加或删除元素时,它都会更改每个元素的属性。
所以我不认为Object.defineProperty
是答案。
我不想使用setInterval
的原因是,间隔大会导致换行不可靠,而间隔小会影响效率。
答案 0 :(得分:2)
遗憾的是,这就是代理如此重要的原因。目前,除了代理之外,没有其他方法可以将代码添加到对象时触发代码。
如您所说,您可以使用Object.defineProperty
或var a = { get x() {...}, set x(value) {...} }
,但不能检测新属性。
大多数框架都依赖于脏检查:在给定的时间比较对象。时机是主要区别所在。
AngularJS(Angular 1.x)为诸如$timeout
和$http
之类的异步操作提供了特殊功能,这是侦听DOM事件的独特方法,该事件将包装您的回调并在代码执行后运行检查
Angular(从2到N的角度)使用Zone.js为您的代码创建“运行上下文”,Zone.js会拦截任何异步回调。该解决方案与AngularJS基本上相同,但是可以自动运行。
React可以执行类似的操作,但是它不会跟踪变量,而是运行渲染器并比较生成的DOM(虚拟DOM)是否不同。