我试图了解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?我花了差不多一整天的时间试图找出错误的地方。有线索吗?
答案 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();