this
keyword in Javascript can sometimes be confusing due to lack of proper knowledge. Here I am going to discuss how this
work.
this
belong to a Javascript function. Inside a function this keyword refers to an object.
var a = 4;
function fun() {
console.log("a = ", this.a); // a = 4
}
fun();
In the above code chunk this
in fun() body refers to global object and as any variable that is globally declared belongs to global object, so this.a
is 4.
This is Default Binding of this
.
Note: If strict mode is used inside the function body using this
, then by default this
will refer to undefined
instead of global object.
What this
refers to only depends on the how the function is called.
Another rules for this
binding
Implicit binding
var prop = 2
function fun1() {
console.log(this.prop)
}
var obj = {
prop: 1,
fun: function fun() {
console.log(this.prop)
},
fun1: fun1
}
obj.fun(); // 1
obj.fun1(); // 1
fun1(); // 2
var obj = {
prop: 1,
fun: function fun() {
console.log(this.prop)
},
}
function containing(cb) {
cb()
}
obj.fun(); // 1
containing(obj.fun) // undefined
Here for both obj.fun()
and obj.fun1()
this
is binded to obj
. This is Implicit binding when one object is used as context object when the function is called.
var obj = {
prop: 1,
fun: function fun() {
console.log(this.prop)
},
}
var fun1 = obj.fun
fun1();
But implicit binding of obj.fun
is lost here because all that matters is how fun
is called. Here fun1
is holding only a reference to fun
function just like fun
property of obj
. As fun1
is called as fun1()
so this
keyword refer to global obj or undefined
depending on strict mode.
Explicit Binding
If we want to call a function with a object as context , without defining function reference property inside the object, we will have to use explicit binding.
Here is call()
and apply()
is our options
var obj = {
a: 1
};
function fun(b, c) {
console.log(this.a);
console.log(b);
console.log(c);
}
fun.call(obj, 2, 3); // 1 2 3
here call
takes an object which is referenced by this
and will invoke the fun
with parameters which are passed to call()
.
apply()
behave similarly except it takes a single array as arguments instead of list of arguments
var obj = {
a: 1
};
function fun(b, c) {
console.log(this.a);
console.log(b);
console.log(c);
}
fun.apply(obj, [2, 3]); // 1 2 3
new Binding
new
keyword can be used with all the functions to create new objects.
function fun(a) {
this.prop = a;
}
var obj = new fun("val");
console.log(obj.prop); // val
when a function is invoked with new
in front of it , it will create a new object and bind this
to the newly created object.
Lexical this
In case of arrow functions these rules does not work. Arrow-functions adopt this
binding from enclosing function or global scope.
function fun() {
setTimeout(() => {
console.log(this.a);
}, 100);
}
function fun1() {
setTimeout(function () {
console.log(this.a);
}, 100);
}
var obj = {
a: 2
};
fun.call(obj); // 2
fun1.call(obj) // undefined
the arrow function which is passed to setTimeout lexically captures this
of fun
s at it's call time
Finally here is the summary of the rules described above to determine this
binding
This is the order of precedence
- if the function is called with
new
thenthis
refers to newly created objectvar obj = new fun();
- if the function is called with
call
orapply
thenthis
refers to explicitly provided object to call or apply.fun.call(obj);
- if the function is called with a context obj then
this
refers that obj.
var obj = {
a: 1,
fun: function () {
console.log(this.a)
}
}
obj.fun() // 1
- Default binding. In strict mode
this
refers toundefined
and without strict mode it refers to global object
fun();