I believe I have found my answer, and it looks like arrow functions SHOULD NOT!!! be used as a method. Functions can be added to an object as a method for specific reasons. This article explains the difference between method functions and method arrow functions.
Functions work well as method implementations: They have a special variable called this that refers to the object via which the method has been invoked. In contrast to other free variables, this isn’t looked up in the surrounding lexical scopes, it is handed to the function via the invocation. As the function receives this dynamically, it is called dynamic this .
To understand this, we have to understand that:
lexical scopes are the syntactic constructs that surround it (a trait of the source code or the lexicon ).
Also:
Its dynamic scopes are the function that called it, the function that called that function, etc. Note the nesting that occurs in both cases.
From Stack Overflow on what is lexical scope:
Lexical Scoping defines how variable names are resolved in nested functions: inner functions contain the scope of parent functions even if the parent function has returned .
Here’s my translation in plain English.
When you write a function as a method, it creates a dynamic scope, so it no longer needs to look to the parent element for what this
should refer to. When you use a function to create a method, that function dynamically says "hey, ignore the usual structure (lexical) and refer to me if you want to use this
.
When we use an arrow function to create a method, it doesn’t come with this automatic behavior and use the usual structure (lexical) to lazily say "eh, whatever my parent element says this
should be, go ahead and refer to it instead of me. It seems that arrow functions are designed to intentionally use lexical instead of dynamic scope, which brings me to the final point. A quote from the original article:
Functions don’t work well as implementations of subroutines, because this is still dynamic. The subroutine call sets it to undefined in strict mode [1] and to the global object, otherwise. That is unfortunate, because the subroutine has no use for its own this, but it shadows the this of the surrounding method, making it inaccessible.
When he says subroutines, he means callback functions like map() and filter() that you mentioned earlier.
This is super cool! The same reason that functions should be used for methods is the same reason they suck as callback functions. A callback function never(?) has a reason to refer to itself with this
since its only goal is to perform an action and return it so that the value can be modified by the higher-order function like map() or filter(). Functions screw this up by doing their dynamic look at me action.
Meanwhile, arrow functions are perfect! An arrow function grabs the callback function, returns the value, and gets out of the way (lexical) so that this
can refer to the scope of the parent function this
, which is the object!
Edit: Another note that shows how this works, is that using .forEach
on an array allows for an argument this
after you write the callback function argument, so that this
can be assigned to whatever you want instead of being lexical and going to global or undefined.
thisArg
Optional
Value to use as this
when executing callback
.
Edit: Not sure if it’s bad manners to mark my own response as the answer, but unless anyone has corrections to make I believe this is the correct answer for anyone looking at this in the future!