Recursive prototype inheritance in nodejs / javascript

In my nodejs program, I have a module called human and it has a prototype object (about) which also has its child method (describe). I am trying to access objects, but I am getting undefined.

Can someone please correct my understanding? what am I doing wrong here?

index.js

var Person = require("./person");
var sam = new Person({name:"Sam",age:23})
sam.about.describe();

      

person.js

module.exports = (function() {
    var person = function(options) {
        if (options && options.name) this.name = options.name;
        if (options && options.age) this.age = options.age;
    }
    person.prototype.about = {
        describe : function(){
            console.log("I am",this.name,"and",this.age,"years old");
        }
    }
    return person;
})();

      

Expected result: "I am Sam and 23 years old" Actual result: "I am undefined and undefined years old"

+3


source to share


3 answers


As others have said, this

your example refers to an object, not a person instance.

One way to get the API you want is to create that namespace about

inside the constructor and use it bind

to set the correct context for the handler describe

.

module.exports = (function() {
    var person = function(options) {
        if (options && options.name) this.name = options.name;
        if (options && options.age) this.age = options.age;
        this.about = {
            describe: function () {
                console.log("I am",this.name,"and",this.age,"years old");
            }.bind(this)
        };
    }

    return person;
})();

      



This way you can simply call

var Person = require("./person");
var sam = new Person({name:"Sam",age:23})
sam.about.describe();

>>> I am Sam and 23 years old

      

+1


source


This is because it this

refers to the direct parent describe

, which about

:

person.prototype.about = {
        describe : function() {
            console.log("I am",this.name,"and",this.age,"years old");
        }
}

      

You will need a weak reference to the main object Person

passed to the namespace about

, for example, and use that instead this

. But I don’t like it, it’s cut off, feels wrong and looks smelly.

Instead, let's just see that it adds a completely new package of functionality to the Person object and allows it to be made a helper:



module.exports = (function() {
    var PersonHelper = function(person) {
        this.person = person;
        describePerson: function() {
            console.log("I am",this.person.name,"and",this.person.age,"years old");
        }
        /* more methods */
    }
    return PersonHelper;
})();

      

So, you could do:

module.exports = (function() {
    var person = function(options) {
        if (options && options.name) this.name = options.name;
        if (options && options.age) this.age = options.age;
    }
    return person;
})();


var Person = require("./person");
var PersonHelper = require("./personHelper");
var sam = new Person({name:"Sam",age:23})
var helper = new PersonHelper(person);
helper.describePerson();

      

+1


source


If you really want to use sam.about.describe

using about

", then one approach is

Object.defineProperty(person.prototype, 'about', {
  get() { 
    return { 
      describe: () => console.log("I am", this.name, "and", this.age, "years old"); 
    };
  }
})

      

This works because the context inside get

is an instance Person

, so the arrow function will refer to it correctly.

0


source







All Articles