JavaScript中有很多关于原型继承的线程,但由于懒惰,这不是副本。我已经完全阅读了所有内容,并且发现了几乎与我找到答案一样多的不同语法方法,所以看来我并不是唯一一个对此主题感到困惑的人!
具体细节:
我目前的做法是这样的。
var Person = function(name) {
this.name = name;
this.greeting = function() {
alert("Greetings, I am " + name);
}
}
var bob = new Person("bob");
bob.greeting();
var Woman = function(name) {
Person.call(this, name);
this.gender = "female";
}
Woman.prototype = Object.create(Person.prototype);
var brenda = new Woman("brenda");
brenda.greeting();
Person.prototype.eats = true;
alert(brenda.eats);
测试了代码后我发现它完美无缺 - 据我所知 - 但我被告知这不是最好的方法,我应该像这样定义构造函数:
Woman.prototype.constructor = Woman;
不要在我的实际构造方法中使用Person.call方法。有两件事,被告知我无法通过第二种方法看到一个简单的方法来传递参数,还有,为什么呢?我正在做的事似乎工作正常。
我错过了什么吗?
在某些情况下,我所做的事情会产生不可预测的错误吗?
任何人都可以给出明确的'正确的'方法及其原因?
答案 0 :(得分:5)
我认为,你所拥有的是最好的方法。你提出的观点是无关紧要的:
Woman.prototype.constructor = Woman;
不是Person.call(...)
的替代品。事实上,这两件事没有任何共同之处,它们有不同的用途:
在子构造函数中调用父构造函数可确保正确初始化子实例。这就像在ES6或其他语言中调用super()
。
分配到constructor
只会恢复Women.prototype.constructor
的原始值。如果您不这样做,brenda.constructor
会引用Person
。这不会对继承的内部工作产生影响,但使用对象的其他代码可能依赖于具有正确值的constructor
。另请参阅Advantages of setting the "constructor" Property in the "prototype"。
所以问题的答案是:你应该同时做到这两点。
有时您会看到作业是Object.create
来电的一部分。这更加准确,因为它重新创建了属性的原始特征(如非可枚举性):
Woman.prototype = Object.create(Person.prototype, {
constructor: {value: Woman, writable: true}
});
FWIW,我相信在ES6中引入class
的原因之一是减少构造函数和原型的混淆。这并不是说你不应该知道它,毕竟,class
或多或少只是语法糖,但它只是让继承更容易:
class Woman extends Person { // almost like Woman.prototype = Object.create(Person.prototype)
constructor(name) {
super(name); // almost like Person.call, but enforced by the interpreter
this.gender = "female";
}
}
答案 1 :(得分:0)
这是JS中的OOP方法
var Person = function(name) {
this.name = name;
}
Person.prototype.greeting = function(){
var newPerson = new Person(this.name);
alert("Greetings, I am " + name);
return newPerson;
}
Person.prototype.toString=function(){
return '[Person "'+this.name+'"]';
}
Woman.prototype = new Person();
Woman.prototype.constructor=Woman;
function Woman(name){
this.name=name;
}
Woman.prototype.toString=function(){
return '[Woman "'+this.name+'"]';
}
var somePerson = new Person('Mr.');
var myPerson = new Woman('She');
alert('somePerson is '+somePerson); // results in 'somePerson is [Person "Mr."]'
alert('myPerson is '+myPerson); // results in 'myPerson is [Woman "She"]'
myPerson.greeting(); // calls a method inherited from Person