В обработчике Proxy, как отличить получение свойства (var) от вызова метода? - PullRequest
0 голосов
/ 25 апреля 2018

У меня есть следующий код, где я использую объект Proxy (прокси), чтобы попытаться перехватить вызовы метода и доступ к свойствам:

Пример: https://jsfiddle.net/r8j4fzxL/2/

(function() {
    'use strict';
    console.clear();

    //some empty class where I want to trap methods props
    class X {
        //...
    }

    let proxy = {
        get: function(target, prop, receiver) {

            console.log('get called: ',
                'target:', target,
                'prop:', prop,
                'receiver:', receiver
            );
            //this is OK, if we are called as a method.
            //but it isn't when called as .prop - because, obviously, we return a function here.
            return function(...args) {
                console.log('wrapper args:', args);
                return 42;
            }
        },


    };


    let p1 = new Proxy(X, proxy);
    //how to distinguish the two in the above proxy:
    console.log(p1.test('some arg passed'));
    console.log(p1.test);
})();

И у меня здесь два вопроса.

  1. Как правило, это правильный путь, если я хочу перехватить доступ к свойствам и методам? Или, может быть, мне стоит каким-то образом использовать .apply trap (хотя и не смог)?

  2. Если это правильный путь (с использованием .get) - тогда как мне узнать, как пользователь получил доступ к ... вещи? Через .foo; или через .foo();?

Ресурсы, которые я использовал и, видимо, не до конца понял:

SO: Эквивалент JavaScript PHP __call

Ответы [ 2 ]

0 голосов
/ 03 июля 2019

На самом деле это решение этого вопроса (который был помечен как дубликат этого, но не является !!): Как получить аргументы функции в обработчике прокси

Вы не можете получить аргументы в ловушке "get", потому что когда вызывается ловушка get, функции еще не вызываются!
Но вы можете создать другой прокси с ловушкой «apply», вот пример:

(function() {
    'use strict';
    console.clear();

    //some empty class where I want to trap methods & props
    class X {

    }

    let proxy = {
        get: function(target, prop, receiver) {
            console.log(arguments);//this gives the arguments of the 'get' trap itself. 


        // normally you trap an existent funcion, in this example we are creating a new one here
        var F = function(...args){
            console.log('Original function call', args);
        }

        return new Proxy(F, {
                apply: function(target, thisArg, argumentsList) {
            // here you have the arguments
            console.log('Trapped function call', argumentsList);
                        return target.apply(thisArg, argumentsList);                        
                }});

        },


    };


    let p = new Proxy(X, proxy);
    console.log(p.test('some arg passed'));

})();

Таким образом, хитрость заключается в том, чтобы перехватить функцию с помощью get first и вместо возврата исходной функции, чтобы вернуть Proxy с apply trap к исходной функции.

0 голосов
/ 25 апреля 2018

Прокси - это, по сути, объекты, которые предоставляют программный способ подключиться к операциям, которые объекты могут выполнять над ними. Исходя из этого, в качестве основы невозможно отличить доступ к свойству от вызова свойства + вызов в точке, к которой осуществляется доступ к свойству. Тот факт, что возвращаемое значение является функцией, это все, что вы можете знать.

С точки зрения языка, p.foo() разбивается на

var p = ...
var foo = p.foo;
foo.apply(p, []);

в качестве примера. p.foo на самом деле не будет доступа к .apply, но дело в том, что доступ к свойству полностью не зависит от того, как возвращаемое значение фактически используется / вызывается.

Таким образом, вы можете проверить, действительно ли значение test уже является функцией, и, если это так, обернуть это значение своей оберткой. Если это не функция, похоже, вы захотите пропустить ее перенос. например,

get: function(target, prop, receiver) {
  var value = Reflect.get(target, prop, receiver);
  if (typeof value === "function") {
    return function(...args) {
      // probably call 'value' with whatever you need
    };
  } else {
    // return the origin value.
    return value;
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...