1

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

→ 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() was called"。实际上是否可以覆盖对象观察者中当前更改的值?

由于这只是一个实验(没有生产代码!),我很欣赏任何类型的解决方案。

4

1 回答 1

1

好吧,你不能真正解决手头的问题。虽然您可以在观察者中再次覆盖更改的值,但观察者仅异步执行,除非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.

于 2013-11-29T19:45:09.387 回答