szeb
szeb

Reputation: 396

Why is the value of 'this' undefined in a function inside a constructor?

I'm trying to implement my own version of promises in Node.js for practice purposes. I'm getting results that I don't understand. I created the following code to show what my problem is about.

class Person {
  constructor(name) {
    this.name = name

    // console.log(this)

    function sayName() {
      console.log(this.name)
    }

    sayName()
  }
}

const joe = new Person('Joe')

I'm getting the error message 'TypeError: Cannot read property 'name' of undefined'. When I call the constructor, the value of 'this' is the newly created object, so if I would uncomment the commented line, I would log out at that line the object that is getting created.

When I call the sayName function, I would expect the value of 'this' to be the global object. In most cases that I've seen it's safe to assume that when you start defining a new function the value of 'this' is the global object. But here it is 'undefined', hence I get the error message.

If I do the same without using the class keyword, and I put the sayName function to the constructor, it behaves as expected, and logs 'undefined', as there is no name property defined on the global object.

function Person(name) {
  this.name = name

  function sayName() {
    console.log(this.name)
  }

  sayName()
}

const joe = new Person('Joe')

I know that there are some safety mechanisms that you trigger when you use the class keyword. My best guess that the difference between the two examples that one of those gets triggered without me knowing it.

Please tell me what causes the difference, why is the value of 'this' undefined in the first example! Thank you

Upvotes: 2

Views: 2536

Answers (1)

sdotson
sdotson

Reputation: 820

It looks like function declarations function() {} lose this context when defined within a constructor. I imagine it has something to do with how constructor is implemented behind the scenes. You can add it back with

sayName = sayName.bind(this);
sayName();

or perhaps the better way is to just not to define functions in the constructor and define it as a class method:

sayName() {
  return this.name;
}

Upvotes: 1

Related Questions