11 August 2013

原文:ECMAScript 6 and Proxy

能够拦截对象的某项特定操作可能非常有用,特别是排除故障时。通过 ECMAScript 6 的新功能代理,拦截变得可行起来。通过在特定对象上创建一个代理,可以使得预定义的处理程序在某些操作发生时收到通知。

在最新的规范草案(15版,2013年5月14日)中,第 15.18 节关于代理对象的内容仍然是空的。不过可以肯定的是,当规范趋于稳定时,将会有更多有用的信息。直接代理的维基页面提供了一些有用的信息。而且在本文写作之际,最新稳定版本的 Firefox 和 Chrome 已经提供了对代理的支持(需要启用实验性 JavaScript)。

译注:在 Chrome 中输入 chrome://flags/#enable-javascript-harmony,启用实验性 JavaScript

阐明代理的最佳方式是通过一个简单的例子(注意:更新后的代码片段使用了新语法 Proxy(target, handler),而不是弃用的 Proxy.create):

var engineer = { name: 'Joe Sixpack', salary: 50 };

var interceptor = {
  set: function (receiver, property, value) {
    console.log(property, 'is changed to', value);
    receiver[property] = value;
  }
};

engineer = Proxy(engineer, interceptor);

在上面的代码中,我们创建了一个简单的对象 engineer。该对象将被替换为通过 Proxy() 创建的代理对象。函数的第二个参数表示一个拦截器,在这里是 interceptor。一个拦截器可以含有多个不同的函数,不过在这个简单的例子中只有一个 set

让我们来看看执行下面的代码会发生什么:

engineer.salary = 60;

拦截器将被触发,它的方法 set 将被调用。因此,我们将得到:

salary is changed to 60

每当 engineer 的某个属性被设置时,拦截器都会知道。而且显然拦截器还可以检测各种其他的操作,例如读取属性、keys()、迭代器等等。更多详情请参考直接代理的维基页面。注意:你也可能对 tvcutsem/harmony-reflect 提供的垫片感兴趣,它可以帮助你使用新的 Proxy API 来代替那些不推荐使用的 API。

除了用于调试外,代理可以帮助库实现数据绑定。因为拦截器可以挂在数据模型上,没有必要再使用替代语法(例如明确调用 set 来更改属性值)或持续跟踪变化(例如脏数据检查)来修改数据模型。

你打算如何使用代理呢?



blog comments powered by Disqus