javascript tutorial - [Solved-4 Solutions] “this” keyword - javascript - java script - javascript array
Problem:
How does the “this” keyword work?
Solution 1:
- Initial global execution context
- This is the case for JavaScript code that is evaluated when a
<script>
element is encountered:
<script type="text/javascript">//<![CDATA[
alert("I'm evaluated in the initial global execution context!");
setTimeout(function () {
alert("I'm NOT evaluated in the initial global execution context.");
}, 1);
click below button to copy the code. By JavaScript tutorial team
When evaluating code in the initial global execution context, ThisBinding is set to the global object, window (§10.4.1.1).
Entering eval code
- ... by a direct call to eval()
- ThisBinding is left unchanged; it is the same value as the ThisBinding of the calling execution context (§10.4.2(2)(a)).
- ... if not by a direct call to eval()
- ThisBinding is set to the global object as if executing in the initial global execution context (§10.4.2(1)).
§15.1.2.1.1 defines what a direct call to eval() is. Basically, eval(...)
is a direct call whereas something like (0, eval)(...)
or var indirectEval = eval; indirectEval(...);
is an indirect call to eval(). See chuckj's answer to (1,eval)('this') vs eval('this') in JavaScript? and this blog post by Dmitry Soshnikov for when you might use an indirect eval() call.
Entering function code
This occurs when calling a function. If a function is called on an object, such as in obj.myMethod()
or the equivalent obj["myMethod"]()
, then ThisBinding is set to the object (obj in the example; §13.2.1). In most other cases, ThisBinding is set to the global object (§10.4.3).
The reason for writing "in most other cases" is because there are eight ECMAScript 5 built-in functions that allow ThisBinding to be specified in the arguments list. These special functions take a so-called thisArg which becomes the ThisBinding when calling the function (§10.4.3).
These special built-in functions are:
Function.prototype.apply( thisArg, argArray )
Function.prototype.call( thisArg [ , arg1 [ , arg2, ... ] ] )
Function.prototype.bind( thisArg [ , arg1 [ , arg2, ... ] ] )
Array.prototype.every( callbackfn [ , thisArg ] )
Array.prototype.some( callbackfn [ , thisArg ] )
Array.prototype.forEach( callbackfn [ , thisArg ] )
Array.prototype.map( callbackfn [ , thisArg ] )
Array.prototype.filter( callbackfn [ , thisArg ] )
click below button to copy the code. By JavaScript tutorial team
Solution 2:
(function(value) {
this.value = value;
$('.some-elements').each(function(elt){
elt.innerHTML = this.value; // uh oh!! possibly undefined
});
})(2);
click below button to copy the code. By JavaScript tutorial team
So here, inside each(), "this" doesn't hold the "value" that you expect it to (from
this.value = value;
click below button to copy the code. By JavaScript tutorial team
above it). So, to get over this (no pun intended) problem, a developer could:
(function(value) {
var self = this; // small change
self.value = value;
$('.some-elements').each(function(elt){
elt.innerHTML = self.value; // phew!! == 2
});
})(2);
click below button to copy the code. By JavaScript tutorial team
Solution 3:
function Person (name) {
this.name = name;
this.sayHello = function () {
console.log ("Hello", this);
}
}
var awal = new Person("Awal");
awal.sayHello();
// In `awal.sayHello`, `this` contains the reference to the variable `awal`
click below button to copy the code. By JavaScript tutorial team
Solution 4:
- global this
In a browser, at the global scope, this is the windowobject
In a browser, at the global scope, this is the windowobject
<script type="text/javascript">
console.log(this === window); // true
var foo = "bar";
console.log(this.foo); // "bar"
console.log(window.foo); // "bar"
click below button to copy the code. By JavaScript tutorial team
In node using the repl, this is the top namespace. You can refer to it as global.
>this
{ ArrayBuffer: [Function: ArrayBuffer],
Int8Array: { [Function: Int8Array] BYTES_PER_ELEMENT: 1 },
Uint8Array: { [Function: Uint8Array] BYTES_PER_ELEMENT: 1 },
...
>global === this
true
click below button to copy the code. By JavaScript tutorial team
In node executing from a script, this at the global scope starts as an empty object. It is not the same as global
\\test.js
console.log(this); \\ {}
console.log(this === global); \\ fasle
click below button to copy the code. By JavaScript tutorial team
function this
Except in the case of DOM event handlers or when a thisArg is provided (see further down), both in node and in a browser using this in a function that is not called with new references the global scope…
<script type="text/javascript">
foo = "bar";
function testThis() {
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
testThis();
console.log(this.foo); //logs "foo"
</script>
click below button to copy the code. By JavaScript tutorial team
If you use use strict;, in which case this will be undefined
<script type="text/javascript">
foo = "bar";
function testThis() {
"use strict";
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
testThis(); //Uncaught TypeError: Cannot set property 'foo' of undefined
</script>
click below button to copy the code. By JavaScript tutorial team
If you call a function with new
the this
will be a new context, it will not reference the global this.
<script type="text/javascript">
foo = "bar";
function testThis() {
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
new testThis();
console.log(this.foo); //logs "bar"
console.log(new testThis().foo); //logs "foo"
</script>
click below button to copy the code. By JavaScript tutorial team
- prototype this
Functions you create become function objects. They automatically get a special prototypeproperty, which is something you can assign values to. When you create an instance by calling your function with new you get access to the values you assigned to the prototype property. You access those values using this.
function Thing() {
console.log(this.foo);
}
Thing.prototype.foo = "bar";
var thing = new Thing(); //logs "bar"
console.log(thing.foo); //logs "bar"
click below button to copy the code. By JavaScript tutorial team
It is usually a mistake to assign arrays or objects on the prototype. If you want instances to each have their own arrays, create them in the function, not the prototype.
function Thing() {
this.things = [];
}
var thing1 = new Thing();
var thing2 = new Thing();
thing1.things.push("foo");
console.log(thing1.things); //logs ["foo"]
console.log(thing2.things); //logs []
click below button to copy the code. By JavaScript tutorial team
- object this
You can use this in any function on an object to refer to other properties on that object. This is not the same as an instance created with new.
var obj = {
foo: "bar",
logFoo: function () {
console.log(this.foo);
}
};
obj.logFoo(); //logs "bar"
click below button to copy the code. By JavaScript tutorial team
- DOM event this
In an HTML DOM event handler, this is always a reference to the DOM element the event was attached to
function Listener() {
document.getElementById("foo").addEventListener("click",
this.handleClick);
}
Listener.prototype.handleClick = function (event) {
console.log(this); //logs "<div id="foo"></div>"
}
var listener = new Listener();
document.getElementById("foo").click();
click below button to copy the code. By JavaScript tutorial team
Unless you bind the context
function Listener() {
document.getElementById("foo").addEventListener("click",
this.handleClick.bind(this));
}
Listener.prototype.handleClick = function (event) {
console.log(this); //logs Listener {handleClick: function}
}
var listener = new Listener();
document.getElementById("foo").click();
click below button to copy the code. By JavaScript tutorial team
HTML this
Inside HTML attributes in which you can put JavaScript, this is a reference to the element.
<div id="foo" onclick="console.log(this);"></div>
<script type="text/javascript">
document.getElementById("foo").click(); //logs <div id="foo"...
</script>
click below button to copy the code. By JavaScript tutorial team
eval this
You can use eval to access this.
function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
eval("console.log(this.foo)"); //logs "bar"
}
var thing = new Thing();
thing.logFoo();
click below button to copy the code. By JavaScript tutorial team
with this
You can use with
to add this
to the current scope to read and write to values on this
without referring to this explicitly.
function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
with (this) {
console.log(foo);
foo = "foo";
}
}
var thing = new Thing();
thing.logFoo(); // logs "bar"
console.log(thing.foo); // logs "foo"
click below button to copy the code. By JavaScript tutorial team
jQuery this
the jQuery will in many places have this refer to a DOM element.
<div class="foo bar1"></div>
<div class="foo bar2"></div>
<script type="text/javascript">
$(".foo").each(function () {
console.log(this); //logs <div class="foo...
});
$(".foo").on("click", function () {
console.log(this); //logs <div class="foo...
});
$(".foo").each(function () {
this.click();
});
</script>