我使用Object.observer使用ES6课程加MaxArt2501 implementation。我有以下代码:
const READY = Symbol("Ready");
const RUNNING = Symbol("Running");
class Foo {
constructor() {
this.value = 1;
this.status = READY;
}
bar() {
this.status = RUNNING;
console.log("bar", this.status );
this.value = this.value + 10;
this.status = READY;
console.log("bar", this.status );
}
}
let foo = new Foo();
Object.observe(foo, function(changes) {
changes.forEach(function(change) {
console.log("foo: ", change);
});
});
我的期望是,当我执行bar()
方法时,观察者函数将被调用3次:将foo.status
从READY
更改为RUNNING
时,更改{ {1}}以及将foo.value
从foo.status
更改为RUNNING
。
但是,这是我在运行READY
时的结果(在Chrome控制台中):
bar()
undefined是从> foo
Foo {value: 1, status: Symbol(Ready)}
> foo.bar()
bar Symbol(Running)
bar Symbol(Ready)
undefined
foo: Object {name: "value", type: "update", object: Foo, oldValue: 1}
> foo
Foo {value: 11, status: Symbol(Ready)}
方法返回的。但无论如何,看起来只是真正观察到bar()
中的变化,而不是foo.value
。
如果我更改foo.status
值"手动"观察到:
foo.status
我可以说,当在类中更改属性类时,它不会通知其观察者。但是,观察到了> foo.status = RUNNING
Symbol(Running)
foo: Object {name: "status", type: "update", object: Foo, oldValue: Symbol(Ready)}
> foo
Foo {value: 11, status: Symbol(Running)}
> foo.status = READY
Symbol(Ready)
foo: Object {name: "status", type: "update", object: Foo, oldValue: Symbol(Running)}
> foo
Foo {value: 11, status: Symbol(Ready)}
方法的foo.value
更改。
有人知道这里发生了什么吗?
谢谢,
Rafael Afonso
更新 - 06/06
我做了一个解决方法,虽然不是很优雅,但我可以在实际实现中使用它作为基础:
bar()
当我跑步时,我得到了这个:
const READY = Symbol("Ready");
const RUNNING = Symbol("Running");
class Foo {
constructor() {
this.value = 1;
this.status = READY;
}
bar() {
// this.status = RUNNING;
console.log("bar", this.status );
this.value = this.value + 10;
// this.status = READY;
console.log("bar", this.status );
}
}
let foo = new Foo();
Object.observe(foo, function(changes) {
changes.forEach(function(change) {
if(change.name === 'value') {
change.object.status = RUNNING;
}
console.log("foo: ", change);
});
});
如您所见,我在可观察方法中更改了> foo.bar()
bar Symbol(Ready)
bar Symbol(Ready)
undefined
foo: Object {name: "value", type: "update", object: Foo, oldValue: 1}
foo: Object {name: "status", type: "update", object: Foo, oldValue: Symbol(Ready)}
。但是,显然在foo执行之后,通知了两个属性更改。
我在想是否更好地使用Java中的Observable和Observer等方法。有人知道一些以这种方式实现的JS库吗?
更新 - 06/06(2)
根据建议,我尝试使用代理:
foo.status
当我跑步时,我得到了这个:
const READY = Symbol("Ready");
const RUNNING = Symbol("Running");
class Foo {
constructor() {
this.value = 1;
this.status = READY;
}
bar() {
this.status = RUNNING;
// console.log("bar", this.status );
this.value = this.value + 10;
this.status = READY;
// console.log("bar", this.status );
}
}
let observer = {
set: function(obj, prop, value) {
let oldValue = obj[prop];
let result = Reflect.set(obj, prop, value);
console.log(prop + ": " + oldValue.toString() + " -> " + value.toString());
return result;
}
}
let foo = new Proxy(new Foo(), observer);
事实上,这正是我所寻求的。虽然Object.observer目标拦截了目标中的所有类型的变化,但我只对属性设置感兴趣。
答案 0 :(得分:1)
快速浏览该回购suggests,每帧只执行一次更新(在具有此类概念的环境中)或每17ms执行一次。
因为JavaScript是单线程的,所以如果你改变一个属性,然后在一个不间断的函数(即不是生成器等)中将其更改回来,那么这个包将无法观察到它。
请记住,Object.observe已不再成为该语言的一部分。建议规范的实际实现可以为您提供每个事件的通知,但是不可能针对这种特定情况进行伪造(至少不包括代理中的每个对象)。