The `this` keyword in JavaScript

Many OOP language provide this to reference instance at runtime, as well as JavaScript. Because of the dynamic feature of JS, figuring out what this points to can be hard sometimes. This passage is aiming at helping to assert this in different contexts.

The Fundamental

The this keyword points to the current execution context at most time. That sounds obscure, but don’t worry. Let’s see some examples to understand it.

1
2
3
4
5
var obj = {};
obj.func = function() {
return this;
}
console.log(obj === obj.func()); // output: true

As we can see, this points to the obj. The function func is invoked by obj.func(), so the execution context is obj.

Then, what will this evaluates without any function wrapped?
Actually, the global object(global in NodeJS and window in browsers) is the execution context in this situation. Following snippet confirms that.

1
2
// test in browsers console
console.log(this === window); // output: true

In Event Handlers

In DOM event handlers, this points to the triggered event.

1
2
3
4
5
6
function eventHandler() {
console.log(this === e.currentTarget); // when triggerd, output: true
}

var elem = document.getElementById('testElem'); // suppose we have an element whose id is testElem
elem.addEventListener('click', eventHandler);

While in inline event handlers, this points to correspond element.

1
<a href='#' onclick="console.log(this.tagName)">test</a>   <!-- when clicked, output: a -->

In Constructors

When a function is used as a constructor, this will point to the new object being constructed.

1
2
3
4
5
function func() {
this.a = 'test';
}
var obj = new func();
console.log(obj.a); // output: test

Do Something Magic

In the first section of this passage, I say ... at most time. In this section, I’d like to show you how to change the usual behavior of this.

apply & call

We can bind this to a particular object by apply or call function.

1
2
3
4
5
6
7
function concat() {
return this.part1 + this.part2;
}

var obj = {part1: 'Hello, ', part2: 'world!'};

console.log(concat.apply(obj)); //output: Hello, world!

We can figure out that concat and obj have no relationship when they are defined, but by using apply we can set this in concat points to obj!

When there is no parameter in function, call behaves as well as apply; the only difference between them is that apply accept an array as parameters while call accept a parameters sequence.

1
2
3
4
5
6
7
8
9
function concat(part3, part4) {
return this.part1 + this.part2 + part3 + part4;
}

var obj = {part1: 'Hello, ', part2: 'world!'};

// the following two statements are equivalent
console.log(concat.apply(obj, [' It\'s ', 'fun!'])); //output: Hello, world! It's fun!
console.log(concat.call(obj, ' It\'s ', 'fun!')); //output: Hello, world! It's fun!

bind

There is also a method to assign a function to an object permanently.

1
2
3
4
5
6
7
function func() {
return this;
}
var obj = {};
var binded = func.bind(obj);

console.log(obj === binded()); // output: true