使用Proxy对象时如何将参数捕获到目标方法?

Dec*_*ler 7 javascript proxy metaprogramming

我正在尝试使用Javascript Proxy对象来捕获传递给我正在代理的目标的"方法"的参数.

请考虑这个例子:

var test = {
    doSomething: function() {
        console.log( arguments.length );
    }
};

var testProxy = new Proxy( test, {
    get: function( target, property, receiver ) {

        // I'd like to have access to any arguments when
        // the property being accessed here is a function
        // that is being called

        return target[ property ];
    }
} );

testProxy.doSomething( 'this', 'is', 'lame' ); // I want to trap those arguments
Run Code Online (Sandbox Code Playgroud)

看起来这些Proxy对象只允许您在属性实际上是一个函数时陷阱访问属性,而不是实际的函数调用及其参数.

在对此事进行了反思之后,我"得到"(原谅双关语)该get方法仅用于属性访问,而不是调用,但后来我希望能够callProxyas中定义类似于方法的东西.好.

也许它在定义一个apply方法时是可行的Proxy,但是我可能不得不为Proxy我想要代理的对象的每个单独方法创建一个对象; 那不是我追求的.

除非我在这里忽略了一个实际的替代可能性:如何在Proxy实现中忽略这一点?!代理的全部意义不是能够拦截方法调用及其参数吗?

或者这是对Javascript的另一个误解,就我而言,Javascript不是一种"经典"OOP语言,而且我正在寻找的功能在Javascript环境中实际上没有意义?

Dec*_*ler 13

实际上有一种方法可以做到这一点,当然!我只是没有仔细考虑过.我可以返回一个'proxy'函数并将参数捕获在那里:

var test = {
    doSomething: function() {
        console.log( arguments.length );
    }
};

var testProxy = new Proxy( test, {
    get: function( target, property, receiver ) {

        switch( property ) {
            case 'doSomething':
              // you just have to return a proxy function
              return function() {
                  // arguments accessible, after all!
                  console.log( 'testProxy::doSomething() arguments.length: ' + arguments.length );

                  // here you can still invoke the original method, of course
                  target[ property ].apply( this, arguments );
              }
            break
        }

        return target[ property ];
    }
} );

testProxy.doSomething( 'this', 'is', 'not', 'so', 'lame', 'after', 'all' );
Run Code Online (Sandbox Code Playgroud)

  • @mayacoda 我认为正确的是:`target[property].apply(target,arguments);` (5认同)

Mil*_*kus 5

另一个片段:)

const obj_hidden = {};

const obj = new Proxy(obj_hidden, {
    get(target, prop) {
        if (typeof target[prop] == 'function') {
          return function (...args) {
            console.dir({ call: [prop, ...args] });
            return target[prop].apply(target, args);
          }
        }
        console.dir({ get: prop });
        return target[prop];
    },
    set(target, prop, value) {
        console.dir({ set: [prop, value] });
        target[prop] = value;
        return true;
    }
});
Run Code Online (Sandbox Code Playgroud)