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 | var obj = {}; |
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 | // test in browsers console |
In Event Handlers
In DOM event handlers, this
points to the triggered event.1
2
3
4
5
6function 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
5function 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
7function 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
9function 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
7function func() {
return this;
}
var obj = {};
var binded = func.bind(obj);
console.log(obj === binded()); // output: true