Javascript - This

About

this is a variable that has a reference value to the scope (namespace)

Because Javascript is scoped on a object level, this is just by default a reference to the object/function where the code is living.

Proof: in the below code, printThis is a property function that lives inside the object obj, the keyword this is then a reference to the object obj.

obj = {
  printThis: function (){
      console.log(this);
   },
  prop1: 2 
}

// printThis' will print the object 'obj' when asking to print 'this'
obj.printThis()

Generally, this is the local scope but it may be changed.

You can set this :

  • in the call of a function (how the function was called)
  • with bind
  • automatically with the arrow function

otherwise it should be the function itself but not always. It may depends of the mode (non–strict/strict mode).

In JavaScript, class methods are not bound by default. If you forget to bind a method and pass it, it will get the value undefined when the function is actually called.

It is a part of how functions work in JavaScript. Generally, if you refer to a method without () after it, you should bind that method.

See also: Object - This

Example

Callback problem

  • Create an object via class with a method
  • Pass this method as callback (ie argument of a function)
  • Call it
  • this is not the object but the function.

To resolve it, you can use the arrow function.

Example:

  • You should not pass
function (callback=myObject.myfunction){
 //
}
  • but
const callbackArrow = ()=>myObject.myfunction();
function (callback=callbackArrow){
 //
}

Management

Initialization

Binding to global object

Binding to the global object is a problematic enough that ES5’s strict mode changes the default binding of this to undefined

A binding to the global scope with this will get the value:

Example:

function hello() {
    "use strict";
    return "hello, " + this.name;
}
try {
    hello(); 
} catch(e) {
  console.log(e.message);
}

Event status

this is:

Direct Assignment is not possible

this can not be assigned directly. The below code is illegal.

try {
    eval('this = 2'); // eval is just there to be able to catch the referenceError 
} catch (e) {
   console.log(e.message); 
}

Assignment with call and bind

this has int.

var double = function(b) {
    return this * 2;
}
console.log(double.call(3));
console.log(double.bind(4)())

Once an function has been bind. Call will have no effect.

var boundFn = function () {
  return this.x;
}.bind( {x: 10} );
 
console.log ( 'boundFn: ' + boundFn() ); // 10
console.log ( 'boundFn + call x=20, still 10 : ' + boundFn.call( {x: 20} ) ); // still 10

this as integer

this has int.

var double = function(b) {
    return this * 2;
}
console.log(double.call(3));

Webtool (Chrome)

Chrome Developer Tool:

Chrome Dev Tool Source Debugger Scope

Example

What is this bound ?

The call expression determines the binding of this, also known as the call’s receiver.

function foo() { 
    console.log( this.bar ); 
} 
var bar = "globalValue"; 
var obj1 = { 
    bar: "obj1Value", 
    foo: foo
};
var obj2 = { 
    bar: "obj2Value" 
}; 

foo(); // "globalValue" - foo was called in the global scope - this = global scope (or window in a browser)
obj1.foo(); // "obj1"  - foo was called in obj1 - this = obj1
foo.call( obj2 ); // "obj2" - foo was called with this = obj2 (the call function)
foo.bind( {bar: "bindValue" } )() // "bindValue" - this was bind to the parameter object
new foo(); // undefined - new sets this to a brand new empty object.

where:

Generally:

Js This Generally Bound To

Example 2

var fn = function (one, two) {
    if ("toString" in this) {
        thisvalue = this.toString
    } else {
        thisvalue = "undefined"
    }
    if (one != undefined) {
        onevalue = one.toString
    } else {
        onevalue = "undefined"
    }
    if (two != undefined) {
        twovalue = two.toString
    } else {
        twovalue = "undefined"
    }
    console.log("*This* has the value '"+thisvalue+"', First argument has the value '"+onevalue+"', Second argument has the value '"+twovalue+"'\n\n");
};

this.toString = "Global";

var foo={ toString: "foo", fn : fn};
var bar={ toString: "bar" };
var darn={ toString: "darn" };
var rat={ toString: "rat" };


// Call of fn with differents context
console.log("foo.fn(bar,darn) gives:");
foo.fn(bar,darn);
console.log("fn(bar,darn) gives;");
fn(bar,darn)
console.log("fn.call(foo,bar,darn) gives;");
fn.call(foo,bar,darn)
console.log("foo.fn.call(rat,bar,darn) gives;");
foo.fn.call(rat,bar,darn)
console.log("setTimeout(fn, 1000) gives;");
setTimeout(fn, 1000);
console.log("setTimeout(foo.fn, 1000) gives;");
setTimeout(foo.fn, 1000);
console.log("setTimeout(function() { foo.fn() }, 1000) gives;");
setTimeout(function() { foo.fn() }, 1000);

Documentation / Reference

Task Runner