-1

I know this keyword is evaluated on the basis of how a function is called. I have the following code:

name='sohan';
income=23232;
class Person{
    constructor(name,income)
    {
        this.name=name;
        this.income=income;
    }
    print(){
        console.log(this.name);
        console.log(this.income);
    }
    getFunc(){
        return this.print;
    }
}

let p1=new Person('bhavuk',10000);
let print=p1.getFunc();
print();

My doubt is print() should bind this to the global context. I expect 'sohan 23232', but it gives error name undefined. Please explain how is this working out. Thanks.

Dilan Tharaka
  • 457
  • 4
  • 13
  • 2
    classes run in strict mode, so the `this` when not specified will be undefined (it won't default to the global object (in browsers the window) like in it does in an object literal). – Nick Parsons Sep 17 '20 at 11:32
  • 2
    @Reyno if we want to answer, I would rather suggest `return this.print.bind(this);` in `getFunc()`. – tevemadar Sep 17 '20 at 11:32
  • No, output in your link is what i expected. My code is working different to what your link suggest. – BHAVUK GARG Sep 17 '20 at 11:34
  • @tevemadar yes i was about to change my comment but you just beat me to it! – Reyno Sep 17 '20 at 11:35
  • 1
    To express was Nick said in slightly different words: In strict mode, `this` inside a "normal" function call is `undefined`. – Felix Kling Sep 17 '20 at 11:37
  • I find *this* (hehe) outcome a bit misleading: I suggested https://stackoverflow.com/questions/2236747/what-is-the-use-of-the-javascript-bind-method as something what OP could check, and that link is completely gone now (apart from remaining "Linked" on the right, which no beginner will ever notice). – tevemadar Sep 17 '20 at 14:21

1 Answers1

1

When you initialize the variables name and income globally without the let, const or var they implicitly become properties of the global object in non strict mode.

Now in the class Person, the method print is defined. The class being run in strict mode implicitly, the this will be undefined always when you get the method reference from class instance:

let print = p1.getFunc();

In the above snippet the method reference is held in the print variable, but the this in the print function is undefined due to strict mode. So when you run the print it will throw an error.

From MDN:

When a static or prototype method is called without a value for this, such as by assigning a variable to the method and then calling it, the this value will be undefined inside the method. This behavior will be the same even if the "use strict" directive isn't present, because code within the class body's syntactic boundary is always executed in strict mode.

In order to point this to the expected object you can use Function.prototype.bind to bind the expected this to the method reference:

name='sohan';
income=23232;

class Person{
    constructor(name,income)
    {
        this.name=name;
        this.income=income;
    }
    print(){
        console.log(this.name);
        console.log(this.income);
    }
    getFunc(){
        return this.print;
    }
}

let p1=new Person('bhavuk',10000);
let myPrint = p1.getFunc();
myPrint = myPrint.bind(p1);
myPrint();

//will pount to the global object where you declare the 2 properties
myPrint = p1.getFunc();
myPrint = myPrint.bind(globalThis);
myPrint();

//Will throw error as the this is undefined
myPrint = p1.getFunc();
myPrint();
Fullstack Guy
  • 14,425
  • 3
  • 18
  • 35