如何在JavaScript中模拟PHP风格的__get()和__set()魔术获取器/设置器?许多人说这目前是不可能的。我几乎可以肯定,这是有可能的,因为像nowjs(http://nowjs.com)这样的项目会做这样的事情。
我知道您可以利用get和set,但是当您不确定属性名称是什么时,这些将无法使用。例如, 如果您希望在创建新属性时执行事件处理程序,该 怎么办?
我想做的例子:
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“和谐”标准中(可能是ES6)。您可以在这里阅读更多内容。引入了带有两个方法的新“代理”对象(即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。
通过查看nowjs源代码,我相信他们可以通过持续监视now对象并在检测到它们时在客户端和服务器之间推送更改来做到这一点。我承认我还没有完全理解他们的代码。
now
在浏览器中,这可以通过一些有趣的setInterval技巧来完成。
setInterval
编辑 :是的,这的确是他们的工作:客户的368行now.js。他们还会做一些技巧,以便一旦检测到新属性,getter和setter就会捕获对它的将来访问,但是这些修改仅在a中每1000毫秒进行一次setTimeout。
now.js
setTimeout
另一个证据表明,在当前的JavaScript中这是不可能的,这是ECMAScript Harmony的代理建议明确设计为支持此类方案,这非常有力地暗示它们目前无法完成。如果可能的话,最新的Mozilla浏览器具有代理实现的原型。显然,V8正在努力添加支持,这可能已经足够了,这取决于最近使用的V8 Node版本。
EDIT2 :哦,很酷,在 服务器 端,nowjs确实使用代理!这很可能意味着它们在Node中已经足够成熟,可以使用。在https://github.com/Flotype/now/blob/master/lib/proxy.js上查看他们的工作。或者只是var Proxy = require("nodejs-proxy")希望他们遵循规范,以便您可以利用MDC和其他地方的文档。
var Proxy = require("nodejs-proxy")