这段代码有什么问题?有人可以帮助我使用JavaScript Object Inheritance吗?我开始觉得自己像个白痴!!
提前致谢, 萨姆
function Human(name, sex) {
this.name = name;
this.sex = sex;
};
function Man(name) {
Man.prototype = new Human(name, "Male");
};
var m = new Man("Sam Striano");
alert(m.name); //<-- = Undefined
答案 0 :(得分:2)
你想要这个:
function Man(name) {
Human.call(this, name, "Male");
}
该代码的作用
看起来你只是试图调用父Human
的构造函数,这与原型继承不同。上面的代码采用Human
的构造函数并将其应用于this
- 一个新的Man
对象。
您的代码的作用
每次创建新人时,Man.prototype = new Human(name, "Male")
行都会更改Man
的原型 。不仅如此,您正在完成重新分配原型对象,因此它仅适用于 之后创建的对象 - 即不是第一个。因此,m.name
未定义。
适当的原型继承
请注意,调用父的构造函数,如上面的代码所示,不会导致Man
自动继承分配给Human.prototype
的任何方法。执行此操作的最佳方法是将Human.prototype
克隆到Man.prototype
中,但不在任何构造函数之外。像这样:
function Man(name) {
Human.call(this, name, "Male");
}
function inherit(parent, child) {
if (Object.create) child.prototype = Object.create(parent.prototype);
else {
for (var key in parent.prototype) {
if (!parent.prototype.hasOwnProperty(key)) continue;
child.prototype[key] = parent.prototype[key];
}
}
}
inherit(Human, Man);
这可能看起来相当冗长,另一种方法可能就是这样做:
Man.prototype = new Human('no name', 'Male');
哪个会起作用,但会导致不必要的副作用,因为我们被迫为prototype
分配了一个dud名称,并让Human
的构造函数调用分配原型的额外时间。如果您沿着此路径走,并稍后更改Human
构造函数,而不仅仅将属性分配给this
,请收到警告。
答案 1 :(得分:1)
在javascript中通常有两个模仿经典继承的步骤:
您的子类构造函数需要调用父构造函数
您的子类原型需要链接到父原型
第一步通常看起来像
function Subclass(blah) {
ParentClass.apply(this, arguments);
}
第二步比较棘手。在实现__proto__
属性的JS环境中,您可以执行
Subclass.prototype = {
__proto__ : ParentClass.prototype,
subclassMethod1: function() { /* ... */ }
}
除非您确切知道脚本的运行位置(例如在node.js环境中),否则您不能依赖__proto__
可用于您的脚本,因此一般方法需要使用{{3 }}:
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
}
Subclass.prototype = Object.create(ParentClass.prototype);
Subclass.prototype.subclassMethod1 = function() { /* ... */ }
这就是它的要点。 ES5运行时可能已经内置了Object.create()
,这很好。
有一些剩余的东西可以完成经典继承的幻觉,比如能够轻松调用父类的覆盖方法。有了我们现在所拥有的,你需要在你的Subclass方法中有类似ParentClass.prototype.overridenMethod.call(this, arg1, arg2)
的东西。
一些OO库将有助于在每个子类实例上定义额外的内容,以便您可以使用this.superclass.overridenMethod(arg1, arg2)
之类的内容。
这种残酷的实施留给了读者一个练习;)
答案 2 :(得分:1)
我认为你所追求的是在Man
的继承属性中拥有Human
类。您已走上正轨,但需要将新Human
实例作为Man
的原型对象应用一次。
function Human(name, sex) {
this.name = "some default";
this.sex = sex;
};
function Man(name) {
if( name !== undefined )
this.name = name;
};
Man.prototype = new Human(name, "Male");
Man.prototype.constructor = Man;
var m = new Man("Sam Striano");
alert(m.name); // alerts "Sam Striano"
alert(m.sex); // alerts "Male"
答案 3 :(得分:1)
据我所知,您应该使用prototype
和constructor
来处理所有内容,并且可以通过这种方式管理inerithance:
// Define superclass
function Human( name, sex ) {
this.name = name;
this.sex = sex;
}
// Define superclass methods
Human.prototype.method1 = function() {
alert( 'This is the call to ORIGINAL method1() with name: ' + this.name + ' and sex: ' + this.sex );
}
// Define subclass
function Man( name, age ) {
this.constructor.apply( this, [ name, 'Man' ] );
this.age = age;
}
// Define subclass inerithance
Man.prototype = new Human();
// Define subclass methods
Man.prototype.method1 = function() {
alert( 'This is the call to OVERWRITE method1() with name: ' + this.name + ' and sex: ' + this.sex + ' and age: ' + this.age );
this.constructor.prototype.method1.apply( this );
}
var m = new Man( 'Sam Satriano', 30 );
m.method1();
// Should alert:
// This is the call to OVERWRITE method1() with name: Sam Satriano and sex: Man and age: 30
// This is the call to ORIGINAL method1() with name: Sam Satriano and sex: Man
希望这会有所帮助。侨!
答案 4 :(得分:1)
如果不进行继承斗争,可以通过将代码更改为以下内容来解决问题:
function Human(name, sex) {
this.name = name;
this.sex = sex;
};
function Man(name) {
// This is how you call the parent's constructor
Human.call(this, name, "Male");
};
// The call to setup the prototype only needs to happen once
// Not in every instantiation of the object
Man.prototype = new Human();
// Have to fix the constructor, right now it's set to Human
Man.prototype.constructor = Man;
var m = new Man("Sam Striano");
>> m.name // outputs "Sam Striano";
>> m instanceof Human // outputs true
这仍然不是一种理想的继承方式。我发布了一些解释什么是良好的JS继承的东西。 http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html