Joel's dev blog

This & Object prototypes (1): this or That?

April 09, 2018

3 min read

Using this is confusing

The first confusion

function test(){
    this.count++; 
    // this is actually a global variable here..
}

test.count = 0; 
// you are adding count property to the test function.
// this.count and test.count are *different*.

test();
test();
test();

console.log(test.count); 
// 0
console.log(window.count); 
// NaN because it was not initialized

Avoiding using this

function test(){
    test.count++; 
    // you are incrementing count property that belongs to test function.
}

test.count = 0; 
// you are initializing the count property. 

test();
test();
test();

console.log(test.count); 
// 3

Or, using Function.prototype.call()

call([thisObj[, arg1[, arg2[,  [, argN]]]]])  

The call() method allows you to point to the object in the first argument. Additional arguments serve as arguments for the object (function) in the first argument.

Simply said, it calls a method of an object, substituting another object for the current object. It allows you to change the this object of a function from the original context to the new object specified by thisObj.

If you omit the first argument, thisObj would be the global object.

function test(num){
    this.count += num;
    // you are incrementing count property that belongs to test function.
}

test.count = 0; 
// you are initializing the count property. 

test.call(test, 1);
test.call(test, -1);
test.call(test, 1); 
// the test function serves as thisObj. 
// Now, this inside test function points to the function itself.

console.log(test.count);  
// 1
window.count = 0;

function test(num){
    this.count += num;
}

test.count = 0; 

test(1);
test(-1);
test(1); 
// this inside test function points to the global object, window. 
// this is not what we want.
console.log(test.count);  
// 0
console.log(window.count);
// 1

Warning on this and scopes

this does not refer to a function’s lexical scope.

Consider the code copied from YDKJS:

function foo() {
    var a = 2;
    this.bar();
}

function bar() {
    console.log( this.a );
}

foo(); // logs undefined

“the developer who writes such code is attempting to use this to create a bridge between the lexical scopes of foo() and bar(), so that bar() has access to the variable a in the inner scope of foo(). No such bridge is possible. You cannot use a this reference to look something up in a lexical scope. It is not possible.”

this

  • this is NOT author-time binding. It’s a runtime binding. It depends on contexts. It’s not about WHERE the function is called from, but HOW the function is called.

Written by Joel Mun. Joel likes Rust, GoLang, Typescript, Wasm and more. He also loves to enlarge the boundaries of his knowledge, mainly by reading books and watching lectures on Youtube. Guitar and piano are necessities at his home.

© Joel Mun 2024