Munish
Munish

Reputation: 988

TypeError while intermixing Prototypal and Constructor pattern in JavaScript

I am trying to understand prototypal pattern and constructor pattern in JavaScript. I read that they are equivalent. So, I thought of intermixing them and got stumped by the results:

Defining the constructor:

function Person(name){
  this.name = name;
  this.describe = function(){ return "Name: "+this.name };
};

Testing the constructor:

munish = new Person('Munish');  // Person { name="Munish",  describe=function()}
munish.constructor;  // Person(name)
munish.constructor.name;  // "Person"
Person.prototype;  // Person {}
Object.getPrototypeOf(munish) === Person.prototype;  // true

Now, trying to use dunder proto and C.prototype to create new objects

nitin = {
  name: 'Nitin',
  __proto__: Person.prototype, 
  // __proto__: Object.getPrototypeOf(munish),  // same as above
}
nitin.describe();  // TypeError: nitin.describe is not a function

Taking another approach by using Object.create() to create new objects

nitin = Object.create(Person.prototype);
nitin.name = 'Nitin';
nitin.describe();  // TypeError: nitin.describe is not a function

Or, if I try

nitin = Object.create(Object.getPrototypeOf(new Person('Nitin')));
nitin.describe();  // TypeError: nitin.describe is not a function

Why the code is throwing TypeError? I spent almost a full day trying to figure out where I went wrong. Any clues?

Upvotes: 0

Views: 35

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074335

Your nitin object doesn't have a describe property because it's not on the prototype. It's a property you're adding to the instance when the constructor is called. If you never call the constructor, it's never added. Just referring to Person.prototype doesn't call Person.

You could put describe on Person.prototype:

function Person(name){
  this.name = name;
}
Person.prototype.describe = function(){ return "Name: "+this.name; };

And then

var nitin = Object.create(Person.prototype);
nitin.name = "Nitin";
nitin.describe();

But of course, you have to duplicate the logic from the constructor every time you do that. If you're going to have a constructor function, it's best to actually use it. If you have a reason for constructing the object without using new, you can still use the constructor to initialize it. (Despite their names, constructors don't actually construct anything, they initialize things. new is what does the actual construction — or, of course, Object.create.) Here's how:

var nitin = Object.create(Person.prototype);
Person.call(nitin, "Nitin");
nitin.describe();

Of course, that's just a really long-winded way to write:

var nitin = new Person("Nitin");
nitin.describe();

Upvotes: 1

Related Questions