代理对象polyfill是否可用谷歌浏览器?

时间:2014-07-23 09:50:39

标签: javascript google-chrome proxy polyfills

这甚至可能吗?其他浏览器怎么样? es6何时“准备就绪”并推出?

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy

顺便说一句。 https://github.com/tvcutsem/harmony-reflect代理无法使用当前的chrome(36.0.n)

4 个答案:

答案 0 :(得分:5)

您可以使用Object.definePropertyObject.observe来模拟代理。我开始想知道polyfill可以支持多少功能,所以我写了一个实现(你可以在gist.github.com/mailmindlin/640e9d707ae3bd666d70看到它)。 我能够模仿代理的所有功能,这些功能并不依赖于运算符重载,到目前为止,这在JavaScript中是不可能的。

但是,您可以获得getset和其他一些工作。您可以使用getter和setter来镜像目标对象的属性:

for (var property in target)
    Object.defineProperty(proxy, property, {
        get: function() {
            if ('get' in handler)
                return handler.get(target, property, proxy);
            else
                return target[property];
       },
       set: function(value) {
           if ('set' in handler)
               handler.set(target, property, value, proxy);
           else
               target[property] = value;
      }});

唯一的问题是getter和setter仅适用于初始化代理时为目标定义的属性,并且delete运算符不起作用(如果删除了目标对象上的属性,代理仍会将其枚举为属性;如果删除代理上的属性,则对象不会发生任何事情。)

要解决此问题,您可以使用Object.observe,在对任一对象进行任何更改时都会调用该target。对caniuse.com的快速检查表明,Chrome和Opera上提供了Object.observe。如果您确实需要在其他浏览器上支持Proxy,则可以轮询proxyvar oldKeys = Object.keys(proxy); setInterval(function() { var keys = Object.keys(proxy); for(var i in keys) if(!oldKeys.includes(keys[i])) //Trigger code for a new property added for(var i in oldKeys) if(!keys.includes(oldKeys[i])) //trigger code for a deleted property oldKeys = keys; //repeat for target object }, 100); 对象,以检查是否已创建或销毁任何属性:

Object.defineProperty

如果您迫切需要代理的更多功能,可以尝试覆盖Object.getOwnPropertyDescriptor和{{1}}等方法,但这可能会导致与其他脚本的兼容性问题,具体取决于您的操作方式。< / p>

简而言之,您可以执行大部分您可能需要使用Proxy for polyfill的内容。谷歌将其添加到浏览器中,我不知道。它显然曾经是V8引擎的一部分,但由于安全问题(没有人详述),它被删除了,据我所知,基于this thread

答案 1 :(得分:1)

更新:虽然我的回答提供了部分解决方案,但mailmindlin solution证明我的主要观点是错误的:您可以Proxy创建一个polyfill。

不,你不能。因为Proxy依赖于几种语言语法元素的特殊(新)行为 - 即.运算符和[索引]运算符 - 所以它不能被模拟填充工具,

唯一的方法是更改​​您使用的语法。例如,如果您想通过代理大写所有字符串属性,您可以创建一个&#34;代理&#34;像这样的对象:

var object = ...
var proxy = {
    get: function proxyGet(key) {
        var res = object[key];
        if (typeof res === "string") {
            res = res.toUpperCase();
        }
        return res;
     }
}

但是,你仍然需要以不同的方式称呼它:

proxy.get("myVar");

而不是

object.myVar;

proxy.myVar

这是新的Proxy语法支持的内容。

注意:您可以几乎创建一个仅适用于方法的polyfill,方法是枚举对象的函数属性,并在代理对象上为每个属性创建代理函数;但是,这不适用于非功能属性,因为您无法动态地影响它们的访问方式。

答案 2 :(得分:1)

我创建了babel插件,它允许你这样做,但它带来巨大的性能影响(对于每个属性访问) - 这是更多的教育示例。

https://github.com/krzkaczor/babel-plugin-proxy

答案 3 :(得分:1)

以下是Google Chrome小组创建的内容: https://github.com/GoogleChrome/proxy-polyfill

但这不是一个完整的实现。