Arrow functions (js)

ref – https://medium.com/@thejasonfile/es5-functions-vs-es6-fat-arrow-functions-864033baa1a
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
https://dmitripavlutin.com/when-not-to-use-arrow-functions-in-javascript/

When creating instances, every use of “new” defined its own ‘this’ value, where ‘this’ references the instance. The function defined in the constructor function will point to “this”. However, another function inside of that will not point to “this”.

Say we create a literal object and assign a reference named “Pets” to point to it.

The object has properties “names” and “owner”, and a description function. Let’s analyze how ‘this’ and the arrow functions affect each other.

In JavaScript, the method is a function stored in a property of an object. In our case, we have a function, and its stored in property “description”. When calling the method, “this” becomes the object that method “description” belongs to.

The “this” context in description is referencing the literal object that pets is pointing to. We see this when we log the ‘this’:


{ names: [ ‘baron’, ‘chief’, ‘axel’ ],
owner: ‘Ricky’,
description: [Function: description] }

We see the object displayed in the console.

Inside of our description function, let’s say we create another function and have a reference called innerFunc pointing to it. We then execute the reference to the function to call it. You’ll see that the ‘this’ inside of innerFunc is undefined.

The reason why is because the inner function does not have a owner, whereas function description does. Inner function see its surrounding scope as function description, and does not detect an object. Hence innerFunc’s this is undefined.

In a more general sense, the solution is that we need to set innerFunc (and our callbacks) up so that it refers to the ‘pets’ literal object.

output:

— description —
{ names: [ ‘baron’, ‘chief’, ‘axel’ ], owner: ‘Ricky’, description: [Function: description] }
— innerFunc —
undefined
— end of innerFunc —
— END OF description —

3 Workaround Solutions

Bind

We use the bind function to bind the pets this to our innerFunc.
Since our function innerFunc’s prototype is Object (as is with any compound objects in JS), we can use the bind function, and pass in the this. We do this inside of description function since description has the correct ‘this’ context.

Once bound, it returns a reference to the innerFunc with the correct this bound. We call that reference as a function and you’ll see that the “this” inside of innerFunc is valid.


— description —
{ names: [ ‘baron’, ‘chief’, ‘axel’ ],
owner: ‘Ricky’,
description: [Function: description] }
— innerFunc —
{ names: [ ‘baron’, ‘chief’, ‘axel’ ],
owner: ‘Ricky’,
description: [Function: description] }
— end of innerFunc —
— END OF description —

If you want multiple inner functions to work, you’ll have to repeat the binding of this object for each inner function.

Pass as a parameter

We can pass the this into the description function. Due to scope visibility, innerFunc will be able to see and use it.

Multiple inner functions will work also because the parameter is visible to them all.


— description —
{ names: [ ‘baron’, ‘chief’, ‘axel’ ],
owner: ‘Ricky’,
description: [Function: description] }
— innerFunc —
{ names: [ ‘baron’, ‘chief’, ‘axel’ ],
owner: ‘Ricky’,
description: [Function: description] }
— end of innerFunc —
— END OF description —

parent scope local var

Inside description function, we can push a reference called self onto the local stack, and have it point to the this object. Since self is at the parent scope of innerFunc, innerFunc sees self, and can use it.

Multiple inner functions will work because the scope of “self” is visible to them all.


output:

— description —
{ names: [ ‘baron’, ‘chief’, ‘axel’ ],
owner: ‘Ricky’,
description: [Function: description] }
— innerFunc —
{ names: [ ‘baron’, ‘chief’, ‘axel’ ],
owner: ‘Ricky’,
description: [Function: description] }
— end of innerFunc —
— END OF description —

Fat Arrow

An arrow function expression has a shorter syntax than a function expression and does not have its own this, arguments, super, or new.target. These function expressions are best suited for non-method functions, and they cannot be used as constructors.

An arrow function does not have its own “this”. The “this” value of the enclosing execution context is used. Thus, when using arrow functions inside of standard functions, the “this” within the arrow function will reference its enclosing function.

This works for multiple inner functions.

Arrow functions are best suited for non-method functions

..such as timer functions, array map functions, sync/async functions.
Any kind of functions used inside of calls should be used as arrow functions
because they can correctly find their outer scope’s this.

Arrow functions should not be used as method functions because for literal objects,
they cannot find the “this” to the literal object and will take the “global” this of
{} instead.

For example:

Arrow functions do not have their own this.

Arrow functions cannot be used as constructors and will throw an error when used with new.

Arrow functions do not have a prototype property.

Another Example

Another example is using globally defined functions like setInterval.
setInterval is a function defined in the global object Window and will be bound to that object.
Thus, whenever we call it, and try to use “this” in a function callback, the “this” will be referred to Window.
What we want is to make sure “this” refers to our Person object.

Thus, we have to use arrow function, because arrow function will get the “this” from its surrounding lexical scope.