The concept that most JavaScript developers struggle with is the this
keyword. This comes with a lack of understanding of what this
means and how it works.
Determining the this
binding for an executing function requires finding the direct call-site(where a function is called from) of that function.
Thumb Rule
The value of this is the object “before dot”, the one used to call the method.
function foo(){
console.log(this.a);
}
let a = 2;
foo(); // 2
Here this
refers to the global object whether in strict mode or not.
Also, consider the following example,
function foo(){
console.log(this.a);
}
const obj = {
a : 4,
}
let a = 2;
obj.foo(); // 4
Using the Thumb Rule this
refers to the obj
.
Losing this
context.
The problem arises when the this
keyword loses its context. Consider the following example,
function foo() {
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
var bar = obj.foo; // function reference/alias!
var a = "oops, global"; // `a` also property on global object
bar(); // "oops, global"
Here, you would have expected that calling bar()
would yield 2
as the output. But it's wrong. The call-site is what matters. The call-site is bar() and thus here this
refers to the global object and globalobject.a
yields oops, global
which is correct output.
Only the top/last level of an object property reference chain matters to the call-site.
Consider,
function foo(){
console.log(this.a);
const obj1 = {
a : 2,
obj2 : obj2,
}
const obj2 = {
a : 3,
foo : foo,
}
obj1.obj2.foo(); // 3
Forcing a function call to use a particular object for this
binding
function foo() {
console.log( this.a );
}
var obj = {
a: 2
};
foo.call( obj ); // 2
foo.call(..)
allows us to force its this
to be obj
.
Arrow functions have no this
.
Arrow functions are special: they don’t have their “own” this. If we reference this from such a function, it’s taken from the outer “normal” function, lexical this
.
Arrow-functions adopt the
this
binding from the enclosing (function or global) scope.
function greet () {
return (a)=> {
console.log(this.a);
}
}
let obj1 = {
a : 'Tarun',
};
let obj2 = {
a : 'Hashnode',
};
let foo = greet.call(obj1);
foo.call(obj2); // 'Tarun' not 'Hashnode' !
Arrow function captures lexical this of greet()
at call-time.
References
Wrap Up
This is it for the this
keyword. I hope you liked the content, there's more on the way. Stay Tuned! 🔥
If you have any suggestions or questions, please let me know in the comments.