使用ES6代理导致任何函数调用"不是函数"

时间:2017-04-21 16:01:54

标签: javascript node.js proxy ecmascript-6 es6-proxy

我试图成为一个鬼鬼祟祟的开发者,我在ES6 Proxies中完成了自己。基本上我想从我写的另一个类中捕获任何get或set属性,并确保它们存储在除了对象之外的其他地方。它看起来像这样:

'use strict'
class MyObject()
{
    superAwesomeFunction(){//super awesome code goes here}
}

const myProxyObject = new Proxy(MyObject, {
get: function(target, name, receiver)
{
    if([CONDITIONS THAT MEET MY DEMANDS])
    {
         // deliver property values if they are
         // my super cool database (if they exist)
    }

    // else just ya know, forward it to the actual MyObject
    // property, if it's an actual property on MyObject
    return target[name];
},
set: function(target, name, value)
{
    if([CONDITIONS THAT MEET MY DEMANDS])
    {
         // set property values if they are
         // to super cool database
    }
    else
    {
        // just set the value to the property, which
        // gets created if it doesn't exist (WHICH IS SO COOL)
        target[name] = value;
    }
    return true;
}

好的关于这个很酷的部分?你可以这样做:

// property that doesn't exist (yet)
console.log(myProxyObject.wholivesinapineappleunderthesea);

// but wait for it...
myProxyObject.wholivesinapineappleunderthesea = 'spongebob';

// bam! now it exists on the object, AND lives in my DB!
console.log(myProxyObject.wholivesinapineappleunderthesea);

虽然很多东西都是愚蠢的,但我无法解释它让我感到多么开心。但是,这有一个问题。还记得我在MyObject()中添加了superAwesomeFunction()吗?好吧,每当我试着打电话给它时,ES6给了我这种悲伤:

  

myProxyObject.superAwesomeFunction不是函数

ES6坐在LIES的宝座上!它完全在那里吗?好的,所以我很确定我错误地捕获了一些东西,因为当我调试时,我发现代理的 get 部分实际上正在接受superAwesomeFunction调用(有意义的是superAwesomeFunction是一个包含函数(){} 的属性

这里是我的问题:有没有人知道任何可以让我保持荒谬的飞行属性仍然可以调用我的superAwesomeFunction()的解决方案?它是应用陷阱吗?

3 个答案:

答案 0 :(得分:2)

那里有一点语法错误......你是围绕原始类包装代理,而不是对象。

尝试:

const myProxyObject = new Proxy(new MyObject(), { ... });

这应该没问题。例如:

> class Blah {
... run() {
..... console.log('yay')
..... }
... }
[Function: blah]
> myProx = new Proxy(new Blah(), {});
blah {}
> myProx.run()
yay

答案 1 :(得分:0)

答案的完整代码在这里,谢谢大家!

'use strict'
class MyObject()
{
    superAwesomeFunction(){
        console.log("this works!");
    }
}

const myProxyObject = new Proxy( new MyObject(), {
get: function(target, name, receiver)
{
    if([CONDITIONS THAT MEET MY DEMANDS])
    {
        // do something cool for yourself
    }

    return target[name];
},
set: function(target, name, value)
{
    if([CONDITIONS THAT MEET MY DEMANDS])
    {
        // do something cool for yourself
    }
    else
    {
        // just set the value to the property, which
        // gets created if it doesn't exist (WHICH IS SO COOL)
        target[name] = value;
    }
    return true;
}
});

答案 2 :(得分:0)

扩展 Sam 的回答。

以下成功:

function Foo() {
  this.bar = function() { console.log('baz'); }
}
let foo = new Proxy(new Foo(), {});
foo.bar();

但是,当将 get 陷阱添加到处理程序时,会抛出“不是函数”:

function Foo() {
  this.bar = function() { console.log('baz'); }
}
let foo = new Proxy(new Foo(), {
  get: function(target, prop) {}
});
foo.bar();

这里的解决方案是添加一个 typeof 检查以检查目标现有函数的默认处理:

function Foo() {
  this.bar = function() { console.log('baz'); }
}
let foo = new Proxy(new Foo(), {
  get: function(target, prop) {
    if (typeof target[prop] === 'function') {
      return target[prop].bind(target);
    }
  }
});
foo.bar();

以下文章提供了更多示例,并提供了与代理处理程序一起使用的漂亮样板:Safely Extending The JavaScript Set Object Using Proxies