监控所有 JavaScript 对象属性(魔法 getter 和 setter)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6985582/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Monitor All JavaScript Object Properties (magic getters and setters)
提问by BMiner
How do I emulate PHP-style __get() and __set() magic getter/setters in JavaScript? A lot of people say that this is currently impossible. I am almost certain that it is possible because projects like nowjs (http://nowjs.com) do something like this.
如何在 JavaScript 中模拟 PHP 风格的 __get() 和 __set() 魔法 getter/setter?很多人说这目前是不可能的。我几乎可以肯定这是可能的,因为像 nowjs ( http://nowjs.com) 这样的项目会做这样的事情。
I know that you can utilize getand set, but these don't work when you're not sure what the property name will be. For example, what if you wanted an event handler to execute when a new property is created?
我知道您可以使用get和set,但是当您不确定属性名称将是什么时,这些将不起作用。例如,如果您希望在创建新属性时执行事件处理程序怎么办?
Example of what I'd want to do:
我想做的例子:
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!
(The question is similar to the following questions:
(问题类似于以下问题:
)
)
EDIT:It looks like this feature is called "dynamic proxies" and should appear in the ECMAScript "Harmony" standard (probably ES6). You can read more here. A new 'Proxy' Object is introduced with a couple methods (I.e. Create() and createFunction() ).
编辑:看起来这个特性被称为“动态代理”,应该出现在 ECMAScript“Harmony”标准(可能是 ES6)中。您可以在此处阅读更多内容。一个新的“代理”对象被引入了几个方法(即 Create() 和 createFunction() )。
One could do this:
可以这样做:
//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)
Bottom line here: it doesn't work in most browsers, but an implementation is available for Node.js: node-proxy.
这里的底线:它在大多数浏览器中不起作用,但是 Node.js 有一个实现:node-proxy。
采纳答案by Domenic
Looking through the nowjs source code, I believe they do this by continuously monitoring the now
object and pushing changes between client and server whenever they are detected. I admit I haven't fully grokked their code yet, however.
查看 nowjs 源代码,我相信他们通过持续监视now
对象并在检测到它们时在客户端和服务器之间推送更改来做到这一点。然而,我承认我还没有完全理解他们的代码。
In a browser, this would be done with some fun setInterval
hacks.
在浏览器中,这可以通过一些有趣的setInterval
技巧来完成。
EDIT: yes, that is indeed what they do: line 368of the client now.js
. They do some more tricksso that once a new property is detected, future access to it is caught by getters and setters, but those modifications are only made every 1000 ms in a setTimeout
.
编辑:是的,这确实是他们所做的:客户端的第 368 行now.js
。他们做了一些更多的技巧,以便一旦检测到新属性,getter 和 setter 就会捕获未来对它的访问,但这些修改仅在setTimeout
.
Another piece of evidence that this is impossible in current JavaScript is that the proxies proposal for ECMAScript Harmonyis designed explicitly to enable such scenarios, implying very strongly that they can't be done currently. Recent Mozilla browsers have a prototype proxies implementation, if perhaps that's enough. And apparently V8 is working to add support, which could be enough depending on what version of V8 Node is using these days.
另一个证明在当前 JavaScript 中这是不可能的证据是ECMAScript Harmony 的代理提案明确设计为支持此类场景,这非常强烈地暗示它们目前无法完成。最近的 Mozilla 浏览器有一个原型代理实现,如果这样就足够了。显然V8 正在努力增加支持,这可能就足够了,具体取决于最近使用的 V8 Node 版本。
EDIT2: oh cool, on the serverside apparently nowjs does use proxies! Which likely means they are mature enough in Node for your usage. See what they do at https://github.com/Flotype/now/blob/master/lib/proxy.js. Or just do var Proxy = require("nodejs-proxy")
and hope they follow the spec so you can take advantage of the documentation from MDC and elsewhere.
EDIT2:哦,酷,在服务器端显然 nowjs 确实使用代理!这可能意味着它们在 Node 中已经足够成熟以供您使用。在https://github.com/Flotype/now/blob/master/lib/proxy.js看看他们做了什么。或者只是var Proxy = require("nodejs-proxy")
希望他们遵循规范,这样您就可以利用 MDC 和其他地方的文档。
回答by Juan Mendes
In Firefox, you can use Object.watch. If you look at this thread, Object.watch() for all browsers?, there's an example of using it something like it in all browsers.
在 Firefox 中,您可以使用Object.watch。如果您查看此线程,Object.watch() 适用于所有浏览器?,有一个在所有浏览器中使用它的例子。
Ooops, I just realized you want to watch all properties, not a specific property... The solution above is to watch a specific property.
哎呀,我刚刚意识到您想查看所有属性,而不是特定属性...上面的解决方案是查看特定属性。
回答by PlagueEditor
Perhaps this postwould help...? That is however, only for specific properties and Gecko based browsers... If you need support for other browsers, its buggy, but you could look into the onpropertychange. Here's the MSDN Page. Hope that helps a bit...
也许这篇文章会有所帮助...?然而,这仅适用于特定属性和基于 Gecko 的浏览器......如果您需要支持其他浏览器,它的错误,但您可以查看 onpropertychange。这是MSDN 页面。希望那有所帮助...