Arrow functions VS Regular functions (scoping of this in function)
Arrow functions VS Regular functions (scoping of this in function)
Yesterday I was going thru HackerRank tutorials of 10 Days of Javascript and had stuck at a problem statement.
The problem statement was far too very easy to solve (probably why it was for beginners 😜)
The problem statement I am referring
At first the problem statement looks very trivial and in fact it is.
If you are not very highly skilled and seasoned JS dev then you would make the same mistake as me 😓.
Image of the problematic code
You can know your skills if you do/don’t find the above code wrong.
I believe just like me, you know where the problem lies. At one point in your life of js development you have come across this and would just require to be reminded of how functions are scoped.
I soon found out the mistake, when I saw the output of the execution and had console logged “this” as a debugging method, the very Brahmāstr (the ultimate weapon) of the developers 😆.
If you are still asking why it is wrong then please let me explain it to you.
Problem Description
The problem lies in as how the two types of function declaration essentially work, moreover how internally the scoping of functions is done.
Arrow Function
There are a bunch of different ways in which arrow functions differ from normal/regular functions (not only in syntax).
- Arrow functions don’t have their own
this
,arguments
,super
,.prototype
. - Arrow functions cannot be used as constructors, hence cannot be used with
new
keyword. - Since arrow function follow normal variable lookup and also they don’t have their own
this
,this
in arrow function is looked up in the enclosing scope (that is the scope where the arrow function is called). - Given that
this
comes from the surrounding lexical context, strict mode rules with regard tothis
are ignored. - Arrow functions cannot be bound to any other scopes, since they don’t have their own bindings of
this
, hence.apply()
,.call()
,.bind()
do not apply (considering their primary usage in concern tothis
), what they would do is just pass the parameter (ignoring any value passing tothis
). - The
[yield](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield)
keyword may not be used in an arrow function's body (except when permitted within functions further nested within it). As a consequence, arrow functions cannot be used as generators. (Referenced from MDN)
So what do all this mean in our issue?
Just for explanation purpose I have saved this in a variable abc and passed it as a parameter to the area function. This helps us to realise that the parameter
_object_
and_this_
are equal.
Visualizing the problem
TLDR: "
this
” in the arrow function is not set as the scope of it’s parent as in regular functions, but is set to the reference of the scope in which it is called. (ie the scope of if block)
SOLUTION
Regular Function
How regular functions work and differ from arrow functions besides the obvious syntactical difference?
- Regular functions have their own bindings of
this
,arguments
,super
,.prototype
. - These functions can be used as constructor because they have their own bindings, due to which these can be used with the
new
keyword. this
in context to function body, have a little different behavior when used instrict
mode as of that when used not used in strict mode.- When not used in
strict
mode then the value ofthis
of function is set to the the context in which the function is declared in. That is, if a function is called as a method of an object, itsthis
is set to the object the method is called on. (Didn’t understand ? Refer the codes below extracted from MDN).
Gist
5. When a function is used as a constructor (with the new
keyword), its this
is bound to the new object being constructed.
6. When used in strict mode then the value of this
of function is set to undefined
. (Didn’t understand? Refer the code below extracted from MDN).
Note: That if a function is called as a method of an object, its
this
is set to the object the method is called on even though it is in strict mode.
Gist
7. Value of this
can be custom set when calling the function by using .apply()
, .call()
.
(Didn’t understand? Refer the codes below)
Note: That in non–strict mode, with call and apply, if the value passed as this is not an object, an attempt will be made to convert it to an object using the internal toObject operation. So if the value passed is a primitive like 7 or ‘foo’, it will be converted to an Object using the related constructor, number 7 is converted by new Number(7) and the string ‘foo’ by new String(‘foo’).
Gist
8. Using .bind()
creates a new function which which has same body and scope as the function it is called upon but the value of this
is permanently set to the value of parameter of .bind()
and then returns the new function. (One more point in the example below, look for examples below)
Gist
9. A function used as getter or setter has its this
bound to the object from which the property is being set or gotten. (Didn’t understand? refer to the code below from MDN).
Gist
TLDR: The value of “
this
“ of function is set to the the context in which the function is called in. That is if a function is called as a method of an object, its “this
“ is set to the object the method is called on.
Working of the solution code
Solution for the problem
This is where I end my article. Any suggestions are most welcome.
Contact me on: