Do you know this?
The value of this
in ECMAScript refers to the execution context of the function.
In ECMAScript there are three execution context; namely global, function and evaluation.
Following example will help to comprehend the concept better.
Global context:
In the global context this
refers to the window object.
console.log(this) // Window
Function context:
In ECMAScript a function can be invoked in five different way:
- method invocation
- function invocation
- constructor invocation
- apply invocation
- call invocation.
The value of this within the function context depends on how the function has been invoked.
Method invocation:
In method invocation pattern this refers to the object (on which the method has been invoked) itself. The value of this gets bound to the object at the time of invocation.
var foo = {
bar : function() {
console.log(this);
return this;
}
}
console.log(foo.bar()) // Object; that refers to foo
var foo = {
bar : function() {
return this;
}
}
console.log(foo === foo.bar()); // true; 'this' returned by bar is nothing but foo
Function invocation:
In function invocation pattern this refers to the window object.
In the broader perspective even function invocation pattern is nothing but method invocation pattern.
The context of the function is window. Lets consider we have a named function baz
as below:
var baz = function() {
console.log(this);
}
In the function invocation pattern baz
can be invoked as:
baz(); // Window
However baz
can also be invoked as:
window.baz(); // Window; as stated in method invocation pattern
All the global (variables, objects, functions) are associated with window and as per the specification, when referring a global the window reference can be omitted. Thus window refers to the global context in function invocation pattern.
Constructor Invocation:
In the constructor invocation pattern, when a function is invoked with new
operator, this
refers to the new object that gets created and returned by the function (provide there is no explicit return statement).
var Foo = function () {// By convention the constructor name starts with upper case letter
console.log(this); // Foo
}
The above code is can be interpreted as
var Foo = function () {// By convention the constructor name starts with upper case letter
// create a new object
// using the object literal
// var this = {};
console.log(this); // Foo, only when invoked as new Foo(); otherwise this will refer to Window
// return this;
}
ES2015 provides class
functionality, which follows the same paradigm.
Apply Invocation & Call Invocation:
Apply and Call invocation differs the way argument is treated. But with respect to this both the pattern behaves in the same way. The beauty of these two patterns is that this can be set to any desired context.
ES5 provides the bind
functionality, it creates a new function that, when called, has its this
keyword set to the provided value.
var bar = {}
var qux = function () {
console.log(this);
}
qux.apply(bar) // Object; that refers to bar
qux.call(bar) // Object; that refers to foo
Evaluation context:
In evaluation context the value of this refers to the context of the scope.
eval('console.log(this)') // Window
var foo = {
bar : function() {
eval('console.log(this)')
}
}
foo.bar(); // Object; that refers to foo
A word of caution: One should refrain from using eval
, most of the ECMAScript ninjas consider “eval
is evil”.
However, I feel that eval
is too powerful to be utilized.
Improper utilization can produce unexpected results, which can be really frightening, for example XSS attacks.
Anonymous function
In strict
mode; it’s undefined
other wise global this
, Window
in browser.
(function() {
'use strict';
console.log(this); // undefined
}());
(function() {
console.log(this); //[object global]
}());
In ES2015 arrow function, this
is the lexical this
.
If you have enjoyed reading this post you can follow me on twitter @sarbbottam and learn about any new posts. Opinions expressed are solely my own and do not express the views or opinions of my employer.