【发布时间】:2019-03-26 14:52:19
【问题描述】:
是否可以不使用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 的原因是因为间隔大会使包装不可靠,而间隔小会对效率产生很大影响。
【问题讨论】:
-
不,你不能在 ES5 中这样做。
-
@Bergi 像 Angular 这样的单页应用程序是如何做到的?
setInterval? -
过去?是的,我想是的,超时或显式触发脏检查。
-
您基本上需要使用angular提供的
$http,它包装了http调用以在最后进行摘要。他们还有一个$timeout和$interval与setTimeout和setInterval类似。当你创建这样一个框架时,你需要使用框架中提供的所有方法,或者你可以调用$scope.$digest()手动触发摘要,如果你做了“角度”之外的事情 -
Angularjs 遵循称为
dirty check的东西,它基本上是从rootScope到所有子作用域的watchers列表迭代,并比较scope值是否已更改。这在后台不断发生,每次运行都称为digest cycle。它们的内部结构可能会变得非常复杂,因此始终建议使用它们的包装方法(例如:$timeout instead of setTimeout)
标签: javascript object ecmascript-5 es5-compatiblity