监控所有JavaScript对象属性(魔法getter和setter)

28
如何在JavaScript中模拟PHP风格的__get()和__set()魔术getter/setter?很多人说这是不可能的。但我几乎可以确定,因为像nowjs(http://nowjs.com)这样的项目就做到了这一点。
我知道你可以利用getset,但当你不确定属性名时,这些方法无法使用。例如,如果您想要在创建新属性时执行事件处理程序怎么办?
以下是我想要实现的示例:
var obj = {};
notify(obj, function(key, value) {
   //key is now the name of the property being set.
   //value is the value of the property about to be set
   console.log("setting " + key + " to " + value);
});
obj.foo = 2; //prints "setting foo to 2"
obj.bar = {a: 2}; //prints "setting bar to [Object]"
//Notice that notify() worked even though 'foo' and 'bar' weren't even defined yet!

(问题类似于以下问题:)

编辑:看起来这个功能被称为“动态代理”,应该出现在ECMAScript“Harmony”标准(可能是ES6)中。您可以在此处阅读更多信息。引入了一个新的'Proxy'对象,并带有一些方法(例如Create()和createFunction())。

可以这样做:

//Constructing an object proxy (proto is optional)
var proxy = Proxy.create(handler, proto);
proxy.foo = 2; //Triggers 'set' function in the handler (read about it)

总之,这在大多数浏览器中无法工作,但是有一个适用于Node.js的实现:node-proxy


1
这个名为代理的特性是 ECMAScript 6 而不是 5 的一部分。 - Raynos
好的,谢谢你指出来了。我修改了我的帖子。 - BMiner
3个回答

13

浏览nowjs源代码,我认为他们通过不断监视now对象,并在检测到更改时在客户端和服务器之间推送更改来实现此目的。 我承认我还没有完全理解他们的代码。

在浏览器中,这将使用一些有趣的 setInterval技巧完成。

编辑: 是的,这确实是他们所做的:客户端now.js的第368行。他们使用其他技巧,以便一旦检测到新属性,未来对它的访问被getter和setter捕获,但是这些修改仅在setTimeout的1000毫秒内进行。

证明这在当前JavaScript中不可能的另一个证据是,ECMAScript Harmony的代理提案专门设计为启用此类场景,这非常强烈地暗示它们目前无法实现。 最近的Mozilla浏览器有一个原型代理实现,也许足够了。而且显然V8正在努力添加支持,这取决于Node现在使用的V8版本。

EDIT2: 很酷,现在看来在服务器端,nowjs确实使用了代理!这很可能意味着它们在Node中已经成熟到可以使用了。你可以查看https://github.com/Flotype/now/blob/master/lib/proxy.js 来了解他们的做法。或者只需使用 var Proxy = require("nodejs-proxy"),希望他们遵循规范,以便您可以利用MDC和其他地方的文档。


好的...我能理解客户端的黑客攻击,特别是因为浏览器兼容性问题。那么服务器端呢?比如在Node.JS上?你认为在那里做些什么是可能的吗? - BMiner
2
我在你评论时刚刚编辑了我的帖子,并分享了我的发现 :) - Domenic

2
在Firefox中,您可以使用Object.watch。如果您查看此线程所有浏览器都可以使用Object.watch(),就会看到在所有浏览器中类似地使用它的示例。
哎呀,我刚意识到您想要监视所有属性,而不是特定属性...上面的解决方案是监视特定属性。

0
也许这篇文章会有所帮助……但这仅适用于特定属性和基于Gecko引擎的浏览器……如果您需要支持其他浏览器,那么虽然有些问题,但您可以研究一下onpropertychange。这是MSDN页面。希望有所帮助……

感谢您的帮助。onpropertychange似乎只适用于DOM对象。这需要适用于普通的原始JS对象。 - BMiner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接