Объяснение функции JS.прототип.применить()

#javascript

Вопрос:

Я немного смущен этим примером:

 Function.prototype.defer = function(ms) {
  let f = this; // I know content of this - it is function f
  return function(...args) {
    setTimeout(() => f.apply(this, args), ms);
  }
};

// check it
function f(a, b) {
  alert( a   b );
}

f.defer(1000)(1, 2);
 

Я знаю, что сначала это (пусть f) содержит функцию f, но как насчет этого в возвращаемой функции? Насколько я понимаю, это не определено, не так ли ( f.apply(undefined, args) ) ? Если да, то почему мы должны использовать apply и почему это работает?

Комментарии:

1. «… как насчет этого в функции-декораторе?» Что вы подразумеваете под «функцией декоратора»?

2. @T. J. Crowder специальная функция, которая принимает другую функцию и изменяет ее поведение. Что-то вроде этого

3. Второе this не имеет значения. Он предназначен для обеспечения контекста для запуска функции, но здесь он не нужен. В этом случае второй this будет ссылаться на глобальный Window объект.

4. Как что ? defer ? Обратите внимание, что «декоратор» имеет определенное значение в JavaScript (хотя это значение все еще уточняется), и вышеизложенное не является декоратором.

5. Ваш вопрос расплывчат. Да, вторая this будет неопределенной в том, как вы используете эту внутреннюю функцию. Ну и что?

Ответ №1:

Это undefined так, как я понимаю

Это в вашем примере использования этого.

почему мы должны использовать call и почему это работает?

Не знаю, почему вы упомянули call об этом . Может быть, ты и намеревался apply . Причина в том, что вы не знаете, что f такое и нуждается ли оно в какой this -то привязке, которая зависит от того, как оно называется. Приятно принять это во внимание и не потерять this привязку при отложенном исполнении.

Вот пример, в котором пользователь defer хочет использовать this :

 Function.prototype.defer = function(ms) {
  let f = this;
  return function(...args) {
    setTimeout(() => f.apply(this, args), ms);
  }
};

// check it
function f(a, b) {
  console.log(this   a   b );
}

f.defer(1000).call(3, 1, 2); // 6