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>
click below button to copy the code. By JavaScript tutorial team

Related Searches to javascript tutorial - “this” keyword