The most powerful keyword in JavaScript is this and many people get tripped by it. People expect it to work like this in Java, but understand that JavaScript is not Java.
Unfortunately understanding behavior of this is little harder if you are new to JavaScript, but certainly its not a magic. And as you start getting to used to this, its rule are actually very simple.
The ‘this’ keyword evaluates to the value of the ‘ThisBinding’ of the current execution context.
The this value depends on the caller and the type of code being executed and is determined when control enters the execution context. The this value associated with an execution context is immutable.
And an execution context is a specification device that is used to track the runtime evaluation of code by an ECMAScript implementation. At any point in time, there is at most one execution context that is actually executing code.
So lets understand how this works in following different contexts-
- Global Context
- Function Context
- Constructor Context
- A DOM Event Handler
1. Global Context
All JavaScript runtimes have a unique object called the global object. In browsers, the global object is the window object. When the JavaScript interpreter initially executes code, it first enters into a global execution context by default and this refers to global object which is window.
1 2 3 4 5 | |
2. Function Context
Whenever you call a function the execution context changes and the new execution context depends on how you invoked the function.
- If you invoke the function using
Function.call()orFunction.apply(),thiswill be set to the first argument passed to.call()/.apply().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
Wait, I didn’t use .call() at line 12 then how the context is window. Basically whenever you make bare function call i.e. without .call()/.apply() as above printContext(), JavaScript will convert the call statement to printContext.call(null).
If the first argument passed to .call()/.apply() is null or undefined, this will refer to window. But the catch here is if you are in strict mode then the value of this will be whatever its set to while entering into execution context, if not defined it will remain undefined.
- If you create function using
Function.bind(),thiswill be bound the first argument that was passed to.bind(). In this approach however you make call to the function doesn’t change value ofthis. CallingprintContext.bind()creates a new function with same body and scope, butthisis permanently bound to first argument ofbind.
1 2 3 4 5 6 7 8 | |
- If you invoke the function as a method of an object,
thiswill refer to that object. But you can still change it to some different object using.call()/.apply().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
3. Constructor Context
When constructing a new object via new operator, JavaScript interpreter creates new empty object, set some properties on it and then call the constructor function on that new object. Thus, in this context the value this is the new object.
1 2 3 4 5 6 | |
4. A DOM Event Handler
Consider the following example, here the value of this in the function handler refers to the button you clicked on. You can observe the same in result tab.
See the Pen this in DOM Event Handler by Shridhar Deshmukh (@shree33) on CodePen.
When you click on the button, the handler is invoked as method of the button, so this refers to the target element. How that happens is here, when you say $("button").click(handler), there will be a new copy of handler created and bound to the button using .bind(). This is done by attachEvent/addEventLister method.
1 2 3 4 5 6 7 | |
Summary
That’s it! If you understand and follow above rules, you will always know what this is.
| Context | Non Strict mode | Strict mode |
| Global Context | window | window |
| .call()/.apply() | First Argument / window | First Argument / undefined |
| .bind() | First Argument | First Argument |
| function() | window | undefined |
| object.function() | object | object |
| Constructor Context | New Object | New Object |
| DOM Event Handler | The HTML Element | The HTML Element |