0

I'm learning Javascript, and I'm a little confused about the "this" keyword. I understand it refers to the specific instance of an object if it's called (i.e. if fido = new Dog("Fido"), then this.method will refer to the specific object it's called on).

However, I was doing a problem off of Javascript.info, and they had the following solution for implementing a Delay wrapper to the Function prototype:

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

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

f.defer(1000)(1, 2); // shows 3 after 1 sec

I'm confused about the use of "this" in the solution. In the first call, (let f = this), it sets f to the specific call of the function. However, 2 lines after, they call f.apply(this, args). I'm confused why they used both the variable f, as well as the actual "this" keyword here... what is the difference in what they refer to?

Thanks!

Edit: The exercise says it's not good practice to change the prototype, but it's there just to test your understanding

Edit2: I've also tried using console.log(this), and it shows up undefined. I'm curious why I need it at all (inputting " " instead of "this" actually yields the same result, which is why I am confused)

maazadeeb
  • 5,922
  • 2
  • 27
  • 40
DarrenF
  • 11
  • 2

4 Answers4

1

As other comments and answers have pointed out, there are several good articles out there that can explain in greater details the "this" keyword. But to answer your question the first "this"(let f = this) is a pointer to the function f, while the second "this"(f.apply(this, args)) is a pointer to the window object because setTimeout is a function of the window object.

mlallinder
  • 33
  • 5
1

I'll annotate the code below:

Function.prototype.defer = function(ms) {
  // The function was called via a reference to a function, so the "this"
  // pointer being captured in "f" will refer to the function that was to be 
  // deferred;
  let f = this;
  return function(...args) {
    // The "this" pointer here refers to the global window object, since
    // the anonymous function returned above didn't explicitly specify
    // a this pointer via bind or other means
    console.log(this);
    setTimeout(() => {
        // Because of the use of an arrow function, the "this" pointer here
        // refers to whatever is the "this" pointer in the containing block
        // Remember, f refers to the original function, so we're invoking it
        // here
        f.apply(this, args)
    }, ms);
  }
};
Evan Trimboli
  • 29,900
  • 6
  • 45
  • 66
0

Essentially, it's because 'this' changes very rapidly. Inside setTimeout it will be different to outside. You use f (though most would use 'self' or similar) to lock down 'this' at a specific point at execution.

How to access the correct `this` inside a callback? is pretty thorough.

Xaraxia
  • 199
  • 9
-1

As defer returns a function, this in f.apply(this, args), ms) would refer to whichever scope the returned function is called at.

Example:

function First () {
  this.name = 'First';
}

First.prototype.defer = function(ms) {
  const f = this;

  return function() {
     setTimeout(() => {
        console.log('Names => ', f.name, this.name);
     }, ms);
  }
}

const first = new First();

function Second() {
  this.name = 'Second';
}

const second = new Second();

second.deferby1000 = first.defer(1000);

second.deferby1000(); // Names => "First" "Second"

Pratheep
  • 936
  • 1
  • 7
  • 17