Javascript's "this" binding

·

4 min read

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 funs 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

  1. if the function is called with new then this refers to newly created object
    var obj = new fun();
    
  2. if the function is called with call or apply then this refers to explicitly provided object to call or apply.
    fun.call(obj);
    
  3. 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
  1. Default binding. In strict mode this refers to undefined and without strict mode it refers to global object
fun();