Reputation: 787
In my nodejs program, i have a module called person and it has a prototype object(about) which also has its child method (describe). I am trying to access objects properties but i am getting undefined.
Could someone correct my understanding? what i am doing wrong here?
var Person = require("./person");
var sam = new Person({name:"Sam",age:23})
sam.about.describe();
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 output: "I am Sam and 23 years old" Actual output: "I am undefined and undefined years old"
Upvotes: 3
Views: 195
Reputation:
If you really want to be able to use sam.about.describe
, with an about
"namespace" containing methods, 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 within get
is that of the Person
instance, and the arrow function will thus refer to it properly.
Upvotes: 0
Reputation: 21532
It's because this
refers to the direct parent of describe
, which is about
:
person.prototype.about = {
describe : function() {
console.log("I am",this.name,"and",this.age,"years old");
}
}
You'd need a weak reference to the main Person
object passed to the about
namespace for example, and use it in place of this
. But I don't like it that way, it is circumvoluted, feels wrong and looks smelly.
Instead, let's just aknowledge the fact that it's a completely new functionality package added to the Person object and let's make a helper for it:
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 then 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();
Upvotes: 1
Reputation: 18389
As others have said, this
in your example refers to the about object, not the person instance itself.
One way to have the API you want, is to create that about
namespace within the constructor, and use bind
to set correct context to the describe
handler.
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
Upvotes: 1