Random memo

this in Javascript function

October 03, 2018

In javascript, if a function is a method of an instance or property of an object, it interprets this inside the function body as the instance or object itself.

function Factory() {
  this.f = function() {
    return this
  }
}

var k = new Factory()
console.log(k === k.f())
// true

as shown above code sample, this in the function refers to the instance itself.

Standalone function

"use strict"

function Factory() {
  this.f = function() {
    function x() {
      return this
    }
    return x()
  }
}

var k = new Factory()
console.log(k === k.f(), k.f())
// false undefined

standalone function x carries its own this, which is undefined when running in strict mode nodejs.

Thick arrow function

function Factory() {
  this.f = function() {
    var x = () => {
      return this
    }
    return x()
  }
}

var k = new Factory()
console.log(k === k.f())
// true

Observing above, one can infer that thick arrow functions don’t carry its own this. They seek it from execution context, just like other variables.

this in an object property function

Let’s see sample code first:

var a = {
  test: function() {
    return this
  },
}
console.log(a === a.test()) // true

var b = {}
b.test = a.test

console.log(b === b.test()) // true

this in an object property function refers to the object itself.

  • cf) function bind
var fn = a.test
console.log(a === fn()) // false
var gn = fn.bind(a)
console.log(a === gn()) // true

Apply, Call

function test() {
  return this
}
console.log(test()) // undefined

var x = {}

console.log(x === test.apply(x)) // true
console.log(x === test.call(x)) // true

this in the standalone function test is given by calling apply, or call with parameter x.

Runtime environments

In fact, this seems to have different values in each of the following 4 differnt runtime environments.

  • node
  • strict mode node
  • browser
  • strict mode browser

Node

console.log(this); //{}

function test() {
  console.log(this === global);
}

test();     //true

new test(); //false

new test() creates an instance and this in the test function refers to that instance.

Strict mode node

"use strict";

console.log(this); //{}

function test() {
  console.log(this === global);
}

test();     //false

new test(); //false

Browser

console.log(this);  //[object Window]

function test() {
  console.log(this === window);
}

test();     //true

new test(); //false

Strict mode browser

"use strict";

console.log(this); //undefined

function test() {
  console.log(this === window);
}

test();     //false

new test(); //false

Compare thick arrow vs traditional function

Thick arrow function has no special meaning with this and handles it like any other variables. The code snippet below run in node. If you want to test it in browser, comment out “use strict”.

"use strict";

var obj = {
  test: function() {
    return this;
  },
  task: v => {
    if (v) {
      this.p = v;
    }
    return this;
  }
};

console.log(obj === obj.test());  //true
console.log(obj === obj.task());  //false

// `this` is object in top level context
console.log(this);                //{}
console.log(this === obj.task()); //true
console.log(this === obj.task(3)) //true
console.log(this);                //{ p: 3 }

Meanwhile, normal function can be used as an object constructor and has its own this as a way of reference to the constructed object itself inside the constructor, like so:

var ref;
var o = new function() {
  ref = this;
  this.x = 1;
}();

console.log(o, ref, o === ref); //{ x: 1 } { x: 1 } true

Sangche

Written by Sangche. Github