It is often confusing to use "this" keyword in JavaScript, if we don't exactly know how it works. I think the confusion comes because people expect "this" keyword in JavaScript to work like âthisâ in Java. There is also some differences in the behavior of "this" in strict and non-strict mode.
What does "this" refer to when used in a function in JavaScript?
In JavaScript "this" always refers to the âownerâ of the function we're executing, or rather, to the object that a function is a method of.
The value of "this" depends on two things:
What does "this" refer to when used in a function in JavaScript?
In JavaScript "this" always refers to the âownerâ of the function we're executing, or rather, to the object that a function is a method of.
The value of "this" depends on two things:
1.) The type of code being executed (i.e., global, function, or eval)
2.) The caller of that code.
2.) The caller of that code.
Before going ahead and exploring "this" we need to understand the JavaScript runtime environments which will hopefully help us in understanding "this" better.
Well, JavaScript code is run in execution context.
Well, JavaScript code is run in execution context.
We can think of the term execution context as the environment or scope in which the current code is being evaluated.
When code is run in JavaScript, the environment in which it is executed is very important, and is evaluated as one of the following:
The JavaScript runtime environment maintains a stack of these contexts, and the top execution context on this stack is the one thatâs actively running. Every time control enters a new execution context , the object that "this" refers to is redetermined.
Remember following rules regarding to whom will "this" refer:
- Global code: The default environment where our code is executed for the first time.
- Function code: Whenever the flow of execution enters a function body.
- Eval code: Text to be executed inside the internal eval function.
The JavaScript runtime environment maintains a stack of these contexts, and the top execution context on this stack is the one thatâs actively running. Every time control enters a new execution context , the object that "this" refers to is redetermined.
Remember following rules regarding to whom will "this" refer:
RULE 1. - GLOBAL CONTEXT
"this" refers to the global object in all global code. And Since all programs start by executing global code, therefore by default, "this" refers to the global object. A global object is an intrinsic object whose purpose is to collect global functions and constants into one object. In browsers, the global object is the window object.
Let us take the following function as an example:
Let us take the following function as an example:
//window object is the global object in the web browsers console.log(this === window) // prints "true"
this.someProp = "test"
console.log(window.someProp)//prints "test"
this.someProp = "test"
console.log(window.someProp)//prints "test"
RULE 2. - FUNCTION CONTEXT
Inside a function there are certain factors which will decide the value of this, e.g - how a function is called, also the strict and non-strict mode have an affect.
Let us take the example of below function called "testFunction", its owner is the page, or rather, the window object (or global object) of JavaScript.
Let us take the example of below function called "testFunction", its owner is the page, or rather, the window object (or global object) of JavaScript.
function testFunction() {
this.color = 'green';
}
testFunction();
console.log(window.color);//prints green
this.color = 'green';
}
testFunction();
console.log(window.color);//prints green
function testFunction() {
"use strict"; //see strict mode
this.color = 'green'; /*throws exception because "this" will not refer to the global object, instead it will remain as "undefined" */
}
testFunction();
console.log(window.color);//prints undefined, because "window" does not have the color property.
"use strict"; //see strict mode
this.color = 'green'; /*throws exception because "this" will not refer to the global object, instead it will remain as "undefined" */
}
testFunction();
console.log(window.color);//prints undefined, because "window" does not have the color property.
In strict mode the value of "this" remains to whatever set to when when entering an execution context. e.g if we would have called the testFunction like window.testFunction(), then inside this function "this" would have referred to "window" object.
There are other things as well which decide the value of "this" inside any function.
1.)"this" in function code invoked using the new operator refers to the newly created object.
Let us take the following example:
There are other things as well which decide the value of "this" inside any function.
1.)"this" in function code invoked using the new operator refers to the newly created object.
Let us take the following example:
function testFunction(myVal) {
this.val= myVal;
}
var obj1 = new doSomething(âdoes not refer to global objectâ);
console.log(obj1.val); //will be - does not refer to global object
console.log(val); //will be - ReferenceError/
this.val= myVal;
}
var obj1 = new doSomething(âdoes not refer to global objectâ);
console.log(obj1.val); //will be - does not refer to global object
console.log(val); //will be - ReferenceError/
But when the same function is called without using a "new" operator then "this" will refer to the global object , as no new object is created since the new operator isnât used :
var obj2 = testFunction(ârefers to global objectâ);
console.log(obj2.val); //will be - undefined
console.log(val); //will be - refers to global object
console.log(obj2.val); //will be - undefined
console.log(val); //will be - refers to global object
2.) call and apply : Every JavaScript functions have two methods, "call" and "apply". When a function is called using "call" or "apply", "this" refers to the first argument passed to "call" or "apply". If the first argument is null or not an object," this" refers to the global object.
Let us see the following example:
Let us see the following example:
var name = "Mark";
var fun = function (txt){
alert(txt + this.name );
};
var obj = {
name: "Tom" };
fun.call(obj, "Hello, ");// return Hello Tom coz this is obj
fun.call(null, "Hello, ");// return Hello Mark coz this is the global object
var fun = function (txt){
alert(txt + this.name );
};
var obj = {
name: "Tom" };
fun.call(obj, "Hello, ");// return Hello Tom coz this is obj
fun.call(null, "Hello, ");// return Hello Mark coz this is the global object
NOTE - with "call" and "apply", if the value passed as "this" is not an object, an attempt will be made to convert it to object using the internal toObject operator.
RULE 3. - EVENT HANDLERS
Look at the below two different ways of event handler bindings:
element.onclick = testFunction;
|
<element onclick="testFunction()">
|
In the first example, when the event handler is executed then "this" will refer to the HTML element. While in the second one (right one) "this" keyword again refers to the global window object.
WHY????
Let us understand this difference in the value of "this" in the two cases.
"this" refers to the parent object inside function code. If we call a function as a property of an object using either dot or bracket notation, "this" will refer to the parent object in the body of the function. Therefore when we do "element.onclick = testFunction;", then we actually copied the function to our onclick property. So if the event handler is executed "this" refers to the HTML element
So this is clear why in this case "this" refers to the HTML element.
Now the question is "what happens in inline event registration?"
WHY????
Let us understand this difference in the value of "this" in the two cases.
"this" refers to the parent object inside function code. If we call a function as a property of an object using either dot or bracket notation, "this" will refer to the parent object in the body of the function. Therefore when we do "element.onclick = testFunction;", then we actually copied the function to our onclick property. So if the event handler is executed "this" refers to the HTML element
So this is clear why in this case "this" refers to the HTML element.
Now the question is "what happens in inline event registration?"
function onclick()
{
testFunction();
}
{
testFunction();
}
In the inline event registration case we do not copy the function and hence the onclick property does not contain the actual function, but merely a function call as follows:
The above event registration actuallty means -Go to testFunction() and execute it.
The "this" keyword is not present in the onclick method, rather onclick method has merely a reference to function doSomething(). Therefore "this" keyword again refers to the global window object.
Following are the ways in which "this" will refer to the HTML element itself:
The "this" keyword is not present in the onclick method, rather onclick method has merely a reference to function doSomething(). Therefore "this" keyword again refers to the global window object.
Following are the ways in which "this" will refer to the HTML element itself:
element.onclick = doSomething;
element.addEventListener('click',doSomething,false);
element.onclick = function () {this.style.color = '#cc0000';}
element.addEventListener('click',doSomething,false);
element.onclick = function () {this.style.color = '#cc0000';}
Following are the ways in which the "this" will refer to the window object/global object :
element.onclick = function () {doSomething()}
element.attachEvent('onclick',doSomething);
element.attachEvent('onclick',doSomething);
Rules for determining what this refers to inside of eval code are a little more complex. Explore them on the link : http://perfectionkills.com/global-eval-what-are-the-options/
Summary:
- By default, "this" refers to the global object.
- When a function is called as a property on a parent object, "this" refers to the parent object inside that function.
- When a function is called with the new operator, "this" refers to the newly created object inside that function.
- When a function is called using call or apply, "this" refers to the first argument passed to call or apply. If the first argument is null or not an object, this refers to the global object.