.call() .apply() .bind() and 'this'

I have been putting off studying the world of 'this' for some time. 'Some' in Hack Reactor time feels like a few months, but in reality, I think it was only last weekend that I first said that I'd dedicate some studying to these concepts. Two weeks ago at most.

There are two main factors that compelled me to finally get it done. First, 'this' is everywhere in React. And as a result, so is 'bind'. Functions get defined in classes and are passed around inside of click handlers and through props, to eventually be called elsewhere in the application. As a result, when they're called, they often lose reference to the 'this' that existed when they were defined. That's where bind comes into play.

Second, we had an exercise where we explicitly asked to explain the differences between .apply and .call and my attempt made no reference to 'this', which is the whole point of using those two functions.

Being brought face to face with my deficiency in the area twice in such stark terms? Ok message received. Time to study.

Here are the materials I reviewed:

*This is an A+ 'this' breakdown
Check out the above link for a cool application of reduce - string concatenation. Love seeing neat and novel (to me) applications of 'familiar' things.
*A practical explanation of bind
*MDN 'the setTimeoutProblem
*MDN call
*MDN bind

Here are my key takeaways:

.call vs .apply

These two functions do the same thing. They take a function and change the reference to 'this'. They let you assign the 'this' to whatever function you're applying them to. The only difference is how they accept function arguments. .call takes multiple arguments while .apply takes a list of arguments.

function.call(this, argument1, argument2)
function.apply(this, [argument1, argument2])

Based on my understanding, this feels like the essential/canonical example of call/apply:

function greet () {
  alert(`Hello, my name is ${this.name}`)
}

const user = {
  name: 'Tyler',
  age: 27,
}

greet.call(user)
>'Hello, my name is Tyler'

How .bind relates

.bind is the same as .apply and .call. The only difference is that it makes the function callable later instead of being called immediately. It sets (one might say, binds) the 'this' reference and then when the function is called, wherever it is called, you know exactly what the 'this' refers to.

Extending from the previous example:

var newFunc = greet.bind(user)
newFunc()
>'Hello, my name is Tyler'

Why do we need these functions?

Javascript determines what this is, where and when a function is called, not where and when it is defined.

This is a tricky concept and really, it brings us to the beginning of the story: when I first saw .bind used, inside of setTimeout.

I understand it a lot better now. While I won't do better job than this explanation (go read it), I feel the need to focus on and clarify the critical part of the explanation:

If you had written:
setTimeout(this.declare, 1000);
That would fail because the function is not actually being called as this.declare(). this.declare is being passed as a function object, which is then called. The dot has to be part of the function call in order to set this...

What made it clear to me was thinking of this.declare as being a free-floating function at the time that setTimeout calls it. This is fixed/attached only when/where it's called. But it's only actually called by setTimeout, which exists within the global scope. What happens if you call this.declare() outside of any function? This will be the window object.

setTimeout(this.declare.bind(this), 1000)
Here, .bind fixes the this and makes it so that wherever this.declare is called, this has a specific and unchanging reference.

I'm walking away from this with a much stronger understanding of 'this' and bind/call/apply.

I look forward to recognizing on my own when to use them in my code - that is, without any prompting or suggestions but just an understanding of where this is defined and what I need it to be.

The canonical example of call/bind?

If there's a second place example, it's this. We used .call in this way when exploring JS class patterns and inheritance in Week 2 of HR:

(from MDN)

function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(name, price) {
  Product.call(this, name, price);
  this.category = 'food';
}

function Toy(name, price) {
  Product.call(this, name, price);
  this.category = 'toy';
}

const cheese = new Food('feta', 5);
const fun = new Toy('robot', 40);

6