2

I have found weird thing with this JavaScript code.

class Person {
    constructor(name) {
        this.name = name;
    }
    speakName() {
        console.log(this.name);
    }
}

var person = new Person("John");
person.speakName(); // John

var speakName = person.speakName;
speakName();        // Error

I made a object named person from Person class. Invoking internal methods directly works fine, however when I reassign the speakName to global variable var speakName, it gives me this exception:

Cannot read property 'name' of undefined

So I thought that this of reassigned var speakName refers global object(global in Node.js, window in Browser JavaScript), however it wasn't both.

class Person {
    constructor(name) {
        this.name = name;
    }
    speakName() {
        // console.log(this.name);
        if(typeof global !== "undefined") {
            console.log(this == global);    // false
        }
        if(typeof window !== "undefined") {
            console.log(this == window);    // false
        }
    }
}

So, what exactly "this" points to? I thought that it was global object, but it seems it's not. Could anyone can explain this?

modernator
  • 4,341
  • 12
  • 47
  • 76
  • 1
    `this` is undefined. In strict mode, the value of `this` does not automatically refer to the global object, where it would otherwise. – VLAZ Sep 29 '18 at 10:52
  • 1
    `this` really is `undefined`, it only refers to the global object in sloppy mode functions because in those `this` is expected to always be an object. – Bergi Sep 29 '18 at 11:02
  • @vlaz I am sorry, apparently, my console was giving other output than a JsFiddle. Basically, you are right. Will delete my comments. – GuyT Sep 29 '18 at 11:02
  • 1
    I am voting to reopen because I don't think this duplicate is correct. Yes, the underlying reason is that the function runs in strict mode but the question is about *classes* rather than simple anonymous functions. The classes do use strict mode by default but that's not readily apparent. The entire problem OP is seeing is because of not knowing about the mechanism that adds strict mode. Explaining what strict mode is doesn't explain how it shows up. – VLAZ Sep 29 '18 at 11:23

1 Answers1

-2

From MDN: The body of a class is executed in strict mode

This means that the value of this is not automatically assigned to the global object when unset and it's instead simply left as undefined. This is the exact error you'd see when running this code

class Person {
    constructor(name) {
        this.name = name;
    }
    speakName() {
        console.log(this.name);
    }
}

var person = new Person("John");
person.speakName(); // John

var speakName = person.speakName;
speakName();        // Error - this is undefined

Compare this with the following example:

var person = {
    fullName: "Fred Flintstone", //changed from "name" to avoid collision with the global name property
    speakName: function() { //this function is in the default "loose" mode
        console.log("My name is: " + this.fullName);
    }
}

var strictPerson = {
    fullName: "Barney Rubble",
    speakName: function() {
        "use strict"; // <-- electing to use strict mode for this function
        console.log("My name is: " + this.fullName);
    }
}

person.speakName(); // <-- "this" refers to "person"
var speakName = person.speakName;
speakName();// <-- "this" refers to the global object

strictPerson.speakName(); // <-- "this" refers to "strictPerson"
var speakNameStrict = strictPerson.speakName;
speakNameStrict();// <-- "this" is undefined

As you can see, in the default mode of execution this is indeed reassigned but with strict mode on you would get the same result as when using a class.

VLAZ
  • 26,331
  • 9
  • 49
  • 67
  • Well, I didn't run the code with "strict mode" both Node.js and browser(latest Chrome). So, what about none "strict mode" case? I just check this code "this == undefined" and it returns true, so it seems like it's undefined as you said. – modernator Sep 29 '18 at 11:20
  • 1
    Again: "The body of a class is executed in strict mode" you didn't *choose* it but it's implied when using an ES6 class. – VLAZ Sep 29 '18 at 11:22