简体   繁体   English

在 Node.js 上使用 Proxy.apply() 不起作用。 这是一个错误还是我做错了?

[英]Using Proxy.apply() on Node.js does not work. Is this a bug or am I doing it wrong?

I am using Proxy to Proxy an object.我正在使用代理来代理一个对象。 The getter and setter work fine like expected. getter 和 setter 可以正常工作。 However, the apply method is never called.但是,从不调用 apply 方法。

    var p = new Proxy({}, {
    /* getter */
    get(target, name) {
        return target[name]
    },
    /* setter */
    set(target, name, value) {
        target[name] = value
    }, 
    /* supposedly called apply */
    apply(target,that,arg) {
        console.log('apply is called, what to do here?')        
    }
})

This way, I can assign something to p or return something even if it doesn't exist.这样,即使它不存在,我也可以将某些内容分配给p或返回某些内容。 When I for instance let the getter function return this例如,当我让 getter 函数返回这个时

get(target, name) {
    return 'getting ' + name
},

and then console.log(p.flappy) I will get the response "getting flappy" even when it doesn't exist.然后console.log(p.flappy)我会得到响应“getting flappy”,即使它不存在。

So far so good but when I try to call flappy doing p.flapppy() it wil throw an error that flappy is not a function.到目前为止一切p.flapppy()但是当我尝试调用 flappy 做p.flapppy()它会抛出一个错误,即 flappy 不是函数。

This is still somewhat obvious because the getter does not return a function.这仍然有些明显,因为 getter 不返回函数。 When I let the getter return a function like this当我让 getter 返回这样的函数时

get(target, name) {
    return function() { return 'this is '+name } 
},

I can call the property without it having to exist.我可以调用该属性而无需它存在。

console.log(
    p.flappy() // this is flappy!
)

So when does apply get called?那么什么时候申请会被调用? Not in the snippet I just showed here and also not in this case:不在我刚刚在这里展示的片段中,也不是在这种情况下:

p.foo = function() {
    console.log('yay!')
    return 'foo!'
}

It does not work to do p.foo() or p.foo.call() or p.foo.apply() , in neither cases apply is called.它不起作用p.foo()p.foo.call()p.foo.apply() ,在这两种情况下都调用 apply 。

The ultimate purpose of this journey is that I want to return a DIFFERENT value depending on whether a property is being read or being called.这个旅程的最终目的是我想根据属性是被读取还是被调用来返回一个不同的值。 Like this:像这样:

   p.someNewProperty // return what the getter function returns

    p.anotherProperty() // return something else here because this is a function call

Is this possible?这可能吗?

I know this is question is a year old, but I ran into this as well and I found a way to do what you are trying to do.我知道这是一个问题,但我也遇到了这个问题,我找到了一种方法来做你想做的事情。 So this is for future reference, as I didn't find correct solutions elsewhere.所以这是为了将来参考,因为我没有在其他地方找到正确的解决方案。

Short version: accessing functions inside an object (or a class) is essentially get ting the property of the object that has the function.简短版本:访问对象(或类)内的函数本质上是get具有该函数的对象的属性。 The trick is to return another Proxy with apply so you can proxy these functions correctly.诀窍是使用apply返回另一个代理,以便您可以正确代理这些功能。

Consider the following object:考虑以下对象:

const myObject = {
  a: 'Hello world!',
  b: x => x * x
};

Accessing a or b shall both be caught by a Proxy's get , because they are properties of the object.访问ab都将被代理的get捕获,因为它们是对象的属性。 You should catch all get and then filter for functions.您应该捕获所有get然后过滤函数。 Once you have a function, you return a new Proxy that catches this particular function with Proxy.apply .一旦你有了一个函数,你就会返回一个新的代理,它用Proxy.apply捕获这个特定的函数。 Then, to let the function execute as intended, inside the Proxy.apply we return a Reflect.apply , which calls the original function with the correct arguments as expected.然后,为了让函数按预期执行,在Proxy.apply我们返回一个Reflect.apply ,它按预期使用正确的参数调用原始函数。

You will end up with this code:你最终会得到这个代码:

const myProxyObject = new Proxy(myObject, {
  get(target, propKey, receiver) {    
    // Calling functions
    if (typeof target[propKey] === 'function') {
      return new Proxy(target[propKey], {
        apply(applyTarget, thisArg, args) {
          console.log(`Calling ${thisArg.constructor.name}.${propKey}(${args})`);
          return Reflect.apply(applyTarget, thisArg, args);
        }
      });
    }

    // Accessing properties
    if (target.hasOwnProperty(propKey)) {
      console.log(`Get value of ${target.constructor.name}.${propKey}`);
      console.log(`Value: ${target[propKey]}`);
    }

    return target[propKey];
  }
});

Demo on jsfiddle jsfiddle 上的演示

You don't get the result of the function, because that would require you to execute it.您不会得到函数的结果,因为那需要您执行它。

Note: it is possible to use this with classes and it works very nicely.注意:可以将它与一起使用,并且效果很好。 The only caveat is that your Proxy will be catching all internal functions as well.唯一需要注意的是,您的代理也将捕获所有内部功能。 In order to prevent logging dozens of valueOf s, I highly recommend to test if a function is native or not with something like this isNative function为了防止记录数十个valueOf ,我强烈建议使用类似 isNative 函数来测试一个函数是否是原生的

As documented on MDN , the apply proxy method is for proxying a function call on the proxy object itself , not a call on a method of the object.MDN 上所述, apply代理方法用于代理对代理对象本身的函数调用,而不是对对象方法的调用。

It only works with functions (as the Proxy target) , not regular object instances, but here is how it would work:它仅适用于函数(作为代理目标) ,而不适用于常规对象实例,但它的工作方式如下:

var p = new Proxy(function() {}, {
    apply: function() {
        console.log('apply called');
    }
});
p();

The ultimate purpose of this journey is that I want to return a DIFFERENT value depending on whether a property is being read or being called.这个旅程的最终目的是我想根据属性是被读取还是被调用来返回一个不同的值。

It is not possible to directly do what you intend, nor would it really make sense.直接做你想做的事情是不可能的,也没有真正的意义。 To call is to read the property.调用就是读取属性。

and after some years...几年后……

yes, you can!是的,你可以! you can return a DIFFERENT value depending on whether a property is being read or being called!您可以根据属性是被读取还是被调用来返回不同的值!

 const authUser = { id: 1 } const user = new Proxy(function () {}, { get (target, property) { return authUser.id }, apply (target, thisArg, args) { // some stuff to get user return { id: args[0] } } }) console.log(user.id) console.log(user(2).id)

or you can use two step proxy.或者您可以使用两步代理。

 const authUser = { id: 1 } const user = new Proxy(function () {}, { get (target, property) { return userProxy(authUser.id, property) }, apply (target, thisArg, args) { return userProxy(args[0]) } }) function userProxy(id, property) { // some stuff to get user const user = { id } return property ? user[property] : new Proxy(user, { get (target, property) { return user[property] } }) } console.log(user.id) console.log(user(2).id)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 JSF 2.2表单上的tagmanager.js不起作用。 我究竟做错了什么? - tagmanager.js on JSF 2.2 form doesn't work. What am I doing wrong? 通过 javascript 更改图像源似乎不起作用。 我究竟做错了什么? - Change image source through javascript does not seem to work. What am I doing wrong? 删除节点时,pruneRoots 函数在下面的树算法中返回 undefined。 无法让它工作。 我究竟做错了什么? - pruneRoots function returning undefined in the below tree algorithm when removing a node. Unable to make it work. What am I doing wrong? puppeteer node.js 代码不起作用。 我不知道为什么 - puppeteer node.js code does not work. and i dont know why Node.js请求数据事件未触发。 我究竟做错了什么? - Node.js request data event not firing. What am I doing wrong? 使用node.js编写Twitter机器人-我在做什么错? - Writing a twitter bot with node.js - what am I doing wrong? 在一条线上推动和取消移动是行不通的。 我究竟做错了什么? - pushing and unshifting in one line doesn't work. what am i doing wrong? 将obj-c类传递给javascript不起作用。 我究竟做错了什么? - Passing obj-c class to javascript doesn't work. What am I doing wrong? apply()不适用于Node.js eventemitter的emit()函数 - apply() does not work on Node.js eventemitter's emit() function 我正在尝试使用nginx反向代理方法托管网站,我正在运行两个Node.js应用程序 - I am trying to host a website using nginx reverse proxy method, i am running two Node.js applications
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM