Разница между функциями стрелок и функциями при использовании декораторов в JavaScript - PullRequest
2 голосов
/ 10 июня 2019

Я немного новичок в JavaScript и в настоящее время выясняю, как работает динамическая область видимости. Теперь я понимаю, как this получает свое значение. Я прочитал все правила и понимаю большинство из них, но у меня возникли проблемы с нахождением головы над этим фрагментом кода, который объясняет разницу между использованием функций со стрелками и функций в декораторах. Вот ссылка на код https://javascript.info/arrow-functions.

Код с функциями стрелок

function defer(f, ms) {
  return function() {
    //What is this? Why use apply? 
    setTimeout(() => f.apply(this, arguments), ms)
  };
}

function sayHi(who) {
  alert('Hello, ' + who);
}

let sayHiDeferred = defer(sayHi, 2000);
sayHiDeferred("John"); // Hello, John after 2 seconds

и с обычными функциями

function defer(f, ms) {
  return function(...args) {
    // What's the purpose of this line? 
    let ctx = this;
    setTimeout(function() {
     // Again why apply? 
      return f.apply(ctx, args);
    }, ms);
  };
}

Вот что мне трудно понять.

  1. Почему мы даже используем apply в обоих случаях? Разве мы не можем сделать это без заявки?
  2. Что бы произошло, если бы я просто позвонил f вместо использования f.apply?
  3. Используем ли мы apply из-за setTimeOut?

Любое объяснение будет оценено.

1 Ответ

2 голосов
/ 10 июня 2019

Твердые вопросы - и, честно говоря - хороший знак, о котором вы думаете.

Почему мы даже используем apply в обоих случаях?Разве мы не можем сделать это без применения?

Стоит знать, .apply (и его брат .bind) происходят из того времени, когда у нас не было функций стрелок, которые автоматическиbind контекст "this".Так что, просто знайте, что они из древнего времени.

Теперь, для чего они (применяются / связываются)?Они действительно нужны только тогда, когда вы хотите назначить «это».В представленных вами случаях вы не ссылаетесь на this - это означает, что вы получите тот же результат, если просто вызовете функции в обычном режиме.Это также отвечает на ваш вопрос:

Что произойдет, если я просто вызову f вместо использования f.apply?

Ничего.У вас будет тот же результат.

Мы используем apply из-за setTimeOut?

Похоже, вы берете несколько примеров, которые вы видели в интернете- но краткий ответ: Да, вы бы использовали..apply или .bind, когда из-за setTimeOut .Но приведенный вами пример скрывает фактический урок.

Вот попытка.


function iReferenceThisForStuff() {
    console.log(this.foo)
}

setTimeout(iReferenceThisForStuff, 10)

// ...10ms pass

// "undefined" is logged because "this" references the global window object

В приведенном выше примере мы передали функцию без привязки тайм-ауту и ​​записали window.foo, потому что- если не установлено явно - this является ссылкой на глобальную область.Это резервное поведение, очень странное - но это то, как оно работает.

Работа с .bind и .apply примерами:


function iReferenceThisForStuff() {
    console.log(this.foo)
}

setTimeout(iReferenceThisForStuff.bind({ foo: "bar" }), 10)

// ...10ms pass

// "bar" is logged because "this" references the object reference passed to `.bind`

// You could have also done...

setTimeout(function () {
   return iReferenceThisForStuff.apply({ foo: "bar" }, /* maybe some additional args */)
}, 10)

// and you would have the same outcome.

Последнее замечание по функциям стрелок.Они связывают this, так как все, что this находится в замыкании, из которого они созданы.

(function () {
   setTimeOut(() => { // This arrow function is instantiated in a closure where `this` is a reference to { foo: "bar" } and is automatically bound.
       console.log(this.foo) // Will eventually log "bar"
   })
}.bind({ foo: "bar" }))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...