Are they really the same?
this and arguments
Let’s look at the following anonymous function example called by setTimeout after 1000 milliseconds. Inside of it, we log the hello variable value and the hello property assigned to this.
It would be to expect that the output would be
hello from this. But instead, the output was the following:
This happens because the value of this is determined accordingly with how that function is called during runtime. So that anonymous function is using the this provided by the setTimeout instead of the one in its scope.
Note: To avoid this issue, people often make use of the self/that pattern to guarantee that they have access to their scope this, instead of the one provided by the caller.
Now looking at the same example, but rewritten using an arrow function.
Let’s see the output.
The output’s exactly what we would expect of the first function example. This happens because arrow functions don’t have their own this and arguments and, instead, make use of scope for everything.
Here we define a function that logs the content of its arguments object and returns an anonymous function that does the same.
The output is exactly what we would expect. This is because the value assigned to the arguments object is related to each function, so each new function will have its arguments object.
Looking at a similar example but using arrow functions.
Now we have the same example but, instead of returning an anonymous function, it returns an arrow function.
As I mentioned above, arrow functions don’t have their own this and arguments. What happens here is that the arguments object used inside of the arrow function is the one from its scope, which, in this case, its the one from the function where it was returned.
Note: ES6 introduced us to rest parameters. Using rest parameters is preferred to using the arguments object, as every function and arrow function will have their one.
Using bind, call and apply
Another thing that works differently using functions and arrow functions is the bind, call, and apply functions. This is because of the behavior of this mentioned above. Since arrow functions don’t have their own this, then trying to bind or pass it with these functions won’t matter.
This example works as intended. The object passed when using the call function is bound to the function this.
As you can see, the output of the hello property assigned to this is undefined because despite trying to assign it when using call, the arrow function has no this for this binding to work — also, since the global this has no hello property it will log undefined.
Arrow functions can’t act as a constructor
Pre ES6, if we wanted to create objects we would make use of a constructor function.
As you can see above, to instantiate an object, we make use of the new keyword to call that function as a constructor. With arrow functions, this doesn’t work because arrow functions can’t be called as constructors.
Note: After ES6, we can leave the constructor functions behind and use a class.
Note 2: Since arrow functions can’t be called as a constructor, trying to use the new.target inside of it will throw an error.
Arrow functions have no prototype
Despite functions having the prototype property, arrow functions do not.
Arrow functions can’t be generators
Arrow functions do not support the use of yield inside of its body, unless inside of a nested function. Also, there is no proper syntax nor implementation for generator arrow functions yet.
To watch out for
Using arrow functions to return object literals must be wrapped with parentheses to guarantee that its keys aren’t treated as labels.
Even if seeming the same, arrow functions do not behave as regular functions. They have no bindings for this and arguments, no prototype, and can’t be used as a generator or as a constructor.
Despite all of this, arrow functions allow writing shorter functions, reducing the size and “noise” we had with functions. All we have to do is to be careful with some of the nuances mentioned throughout this article.
I hope you enjoyed and stay tuned for future posts.