正在覆盖Object.obsoe()中的属性

Overwriting property in Object.observe()

本文关键字:属性 obsoe 覆盖 Object      更新时间:2023-10-18

我想使用Chrome的实验对象.obsobserve()来覆盖对象上设置的所有函数:

→jsFiddle

var obj = {};
Object.observe(obj, function (changes) {
    changes.forEach(function (data) {
        if ((data.type == "new" || data.type == "updated") &&
            typeof data.object[data.name] == "function" &&
            typeof data.object[data.name].isWrapper == "undefined") {
            data.object[data.name] = function () {
            };
            data.object[data.name].isWrapper = true;
        }
    });
});
obj.helloWorld = function () {
    console.log("helloWorld() was called");
};
obj.helloWorld();

不幸的是,控制台仍然显示"helloWorld()被调用"。是否真的可以覆盖对象观察器中当前更改的值?

由于这只是一个实验(没有生产代码!),我很感激任何一种解决方案。

好吧,你不能真正解决手头的问题。虽然您可以在观察器中再次覆盖更改的值,但观察器仅异步执行,除非显式调用了Object.deliverChangeRecords,因此它仅在obj.helloWorld()已按定义的顺序调用后执行。

我更新了你的小提琴以显示:

var obj = {};
function obs(changes) {
    changes.forEach(function (data) {
        if ((data.type == "new" || data.type == "updated") &&
            typeof data.object[data.name] == "function" &&
            typeof data.object[data.name].isWrapper == "undefined") {
            data.object[data.name] = function () {
                console.log("intercepted", data.name);
            };
            data.object[data.name].isWrapper = true;
        }
    });
}
Object.observe(obj, obs);
obj.helloWorld = function () {
    console.log("helloWorld() was called");
};
// Will call the original function, as changes are not yet delivered.
obj.helloWorld();
Object.deliverChangeRecords(obs); 
// Will call the intercepted function, as the changes were explicitly delivered synchronously.
obj.helloWorld();
obj.helloWorld2 = function () {
    console.log("helloWorld2() was called");
};
// Will call the intercepted function, as first the changes will be delivered (end of turn) and only then the timeout callback will be called.
setTimeout(function() { obj.helloWorld2(); }, 0);

不过,不完全确定setTimeout比特是由规范建议隐含授权的,还是仅仅是实现细节。

由于在没有明确执行Object.deliverChangeRecords的修改代码的情况下,无法立即同步观察任何更改,因此这个API并不真正适合您想要实现的目标,至少在当前的规范建议中是这样。

Object.observe的一个可行的替代方案可能是Proxy,它实际上是用来做这样的事情的,IIRC也可以在Chrome中使用(打开了实验和声功能)。这是一把使用Proxy的小提琴。