Определите, вызывается ли функция или вызывается в обработчике прокси - PullRequest
2 голосов
/ 02 июня 2019

У меня есть прокси-обработчик, подобный этому:

let handler = {
        get: function(target, name) {
            let member = target[name];
            if (typeof member === 'function') {
                return function() {
                    //
                }
            }
            return member;
        }
    }

Каждый раз, когда вызывается метод для объекта Proxy:

var obj = {
    foo: function() {
        //
    }
}

var p = new Proxy(obj, handler);
p.foo();

... Он вызывает функцию, которая была возвращена изhandler получатель.Но проблема в том, что когда метод доступен , а не , вызывается следующим образом:

p.foo;

Возвращается полное определение функции.

Есть ли способ, с помощью которого я мог бы проверить, осуществляется ли доступ к методу (p.foo) или вызывается (p.foo())?Я пытаюсь получить что-то вроде:

if (typeof member === 'function' && member.isBeingCalled()) {
    return function() {
        //
    }
}

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

1 Ответ

1 голос
/ 02 июня 2019

Да, это возможно, но для того, чтобы заставить его работать, вам нужно учитывать, что происходит при вызове метода

 o.foo()

, поскольку происходит больше, чем вы думаете.

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

Вторая операция - это вызов этой функции в качестве метода с помощью function.prototype.apply .Это вызывает функцию с ее значением this, связанным с o.

Поэтому для достижения желаемого поведения необходимо указать значение свойства o.foo вместо o сам.ваш прокси будет использовать ловушку применения для перехвата и изменения вызова функции, что является значением этого свойства.Это хорошо описано MDN.https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/apply

По сути, вы бы написали что-то вроде

const foo = o.foo;
const proxiedFoo = new Proxy(foo, {
  apply(target, thisArg, argumentsList) {
    if (thisArg) {
      // this function is being invoked as a method
    }
  }
});

o.foo = proxiedFoo;
...