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 😓.
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 to this 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 to this ), what they would do is just pass the parameter (ignoring any value passing to this ).
The 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.
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 in strict mode as of that when used not used in strict mode.
When not used in strict mode then the value of this 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, its this 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.
This is where I end my article. Any suggestions are most welcome.
Contact me on:
Top comments (0)