Charlie Fish
Charlie Fish

Reputation: 20496

JavaScript - Access Class Instance Property in Prototype Function

I have the following code:

class Pet {
    constructor(name) {
        this.petName = name;
    }
}

Pet.prototype.speak = {
    name: function() {
        console.log(this.petName);
    }
};

// -----------------------------------------------

const myPet = new Pet("Max");
myPet.speak.name();

I expect this code to print Max, but instead it prints undefined.

If I change the console.log to console.log(this); it prints { name: [Function: name] }. Which makes me think that function doesn't have access to the instance properties.

How can I ensure that this function has access to the instance?

Upvotes: 2

Views: 1608

Answers (2)

Paul
Paul

Reputation: 141839

When you call a function like this: myPet.speak.name(); then inside that function this refers to myPet.speak. In your case that is an object with one property (name) whose value is a function.

If you make speak itself be a function instead of an object, and use the property petName instead of name, it will work:

class Pet {
    constructor(name) {
        this.petName = name;
    }
}

Pet.prototype.speak = function() {
    // myPet has a `petName` property, but no `name` property
    console.log(this.petName);
};

const myPet = new Pet("Max");
myPet.speak(); // this will be `myPet` inside the function

Upvotes: 1

Dacre Denny
Dacre Denny

Reputation: 30360

If you're targetting or have support for ES6 language features, one way to achieve what you want would be via a get method combined with an arrow function.

The get method would be declared get speak() which means it can be called without paranthesis. This method would return an object that contains a name() arrow function. Use of the arrow function here allows you to access the enclosing Pet instance via the this keyword directly:

class Pet {
    constructor(name) {
        this.petName = name;
    }
    
    // Get method allows the speak method to be called without ()
    get speak() {
      return {
        // Arrow function causes this.petName to refer to petName 
        // field of this class instance 
        name: () => {
          console.log(this.petName);
        }
      }
    }
}
 
const myPet = new Pet("Max");
myPet.speak.name();

const yourPet = new Pet("Min");
yourPet.speak.name();

Here is more information on the get method syntax and language feature.

Upvotes: 3

Related Questions