在JavaScript中混合Prototypal和Constructor模式时出现TypeError

时间:2015-06-13 10:38:31

标签: javascript

我试图了解JavaScript中的原型模式和构造函数模式。我读到它们是等价的。所以,我想到混合它们并被结果困扰:

定义构造函数:

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

测试构造函数:

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

现在,尝试使用dunder proto和C.prototype来创建新对象

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

使用Object.create()创建新对象

采用另一种方法
nitin = Object.create(Person.prototype);
nitin.name = 'Nitin';
nitin.describe();  // TypeError: nitin.describe is not a function

或者,如果我尝试

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

为什么代码会抛出TypeError?我花了差不多一整天的时间试图找出错误的地方。有线索吗?

1 个答案:

答案 0 :(得分:1)

您的nitin对象没有describe属性,因为它不在原型上。当调用构造函数时,它是您添加到实例的属性。如果你从不调用构造函数,那么它永远不会被添加。仅提及Person.prototype不会调用Person

您可以将describe放在Person.prototype上:

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

然后

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

但是,当然,每次执行此操作时都必须从构造函数中复制逻辑。如果您要使用构造函数,最好实际使用它。如果您有理由在不使用new的情况下构造对象,则仍可以使用构造函数对其进行初始化。 (尽管它们的名称,构造函数实际上并不构造任何东西,但它们初始化事物。new是实际构造 - 或者当然是Object.create。)这是如何:

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

当然,这只是一种非常冗长的写作方式:

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