Незаконный вызов при перехвате вызовов методов с помощью прокси-сервера javascript

Может кто-нибудь объяснить следующий вывод

var handler = {
  get: function(target,key, receiver){
    return new Proxy(Reflect.get(target, key, receiver),handler);
  }, 
  apply: function(target, thisArg, args){
    Reflect.apply(target, thisArg, args);
  }
}

var p = new Proxy(window, handler);
p.alert("Alert"); // Throws illegal invocation error

var alias = p.alert;
alias("Alert") // Even this works which is baffling for me

var p = new Proxy(Reflect.get(window, "alert"), handler);
p("Alert"); // works as expected

Первый оператор выдает недопустимую ошибку вызова, а второй — нет. Оба они выглядят одинаково для меня, и я не понимаю, как первый оператор не имеет требуемого контекста this во время Reflect.apply


person Ayush Goel    schedule 21.08.2018    source источник
comment
Ответ @ibrahimmahrir, относящийся к вашему прокси, см. в сообщении об ошибке, вызванном alert.call(new Proxy(window, {}), "alert").   -  person Ry-♦    schedule 22.08.2018
comment
Когда функция вызывается без явного контекста, контекст будет window. Явный контекст: как в obj.func, так и в func.call(obj) контекст будет obj.   -  person ibrahim mahrir    schedule 22.08.2018
comment
@Ry- Спасибо за этот замечательный пример, он действительно отвечает на вопрос. Таким образом, передача прокси-объекта цели в качестве контекста — это не то же самое, что передача самой цели в качестве контекста, что на самом деле имеет смысл.   -  person Ayush Goel    schedule 22.08.2018


Ответы (1)


Просто alert нужен window в качестве контекста, иначе он выдает эту ошибку. К прокси отношения не имеет. Эти два примера вызывают одну и ту же ошибку:

var obj = {};
alert.call(obj, "hello!");           // doesn't work!

а также:

var obj = { alert: alert };
obj.alert("hello!");                 // doesn't work!

В вашем коде, если вы установите контекст p.alert на window, он работает:

p.alert.call(window, "hello!");      // works!

var handler = {
  get: function(target, key, receiver) {
    return new Proxy(Reflect.get(target, key, receiver), handler);
  },
  apply: function(target, thisArg, args) {
    Reflect.apply(target, thisArg, args);
  }
}

var p = new Proxy(window, handler);
p.alert.call(window, "Alert");

Два других примера из вашего кода работают, потому что контекст window.

person ibrahim mahrir    schedule 21.08.2018
comment
Спасибо, я отмечу это как ответ, но причина, по которой прокси здесь становится актуальным, заключается в том, что если я вызову Reflect.apply внутри самого обработчика получения, эта проблема больше не возникает, потому что теперь я вызываю метод с захваченным целевым контекстом. . - person Ayush Goel; 22.08.2018