好像Bla2
没有从Bla
类继承它!
没错。你没有做任何事情来连接那里的继承,你刚刚创建了一个名为base
的Bla2
成员,它是一个Bla
实例。 base
不是JavaScript中的特殊标识符。
设立继承JavaScript中的典型方式是这样的:
// The base constructor function
function Base(x) {
// Base per-instance init
this.x = x;
}
// An example Base function
Base.prototype.foo = function() {
console.log("I'm Base#foo, x = " + this.x);
};
// The Derived constructor function
function Derived(x, y) {
// Normally you need to call `Base` as it may have per-instance
// initialization it needs to do. You need to do it such that
// within the call, `this` refers to the current `this`, so you
// use `Function#call` or `Function#apply` as appropriate.
Base.call(this, x);
// Derived per-instance init
this.y = y;
}
// Make the Derived.prototype be a new object backed up by the
// Base.prototype.
Derived.prototype = Object.create(Base.prototype);
// Fix up the 'constructor' property
Derived.prototype.constructor = Derived;
// Add any Derived functions
Derived.prototype.bar = function() {
console.log("I'm Derived#bar, x = " + this.x + ", y = " + this.y);
};
...其中Object.create
是ES5,但它是可以很容易地大多匀的事情之一。 (或者你可以使用一个函数,只做最低限度,但不尝试做所有的Object.create
;见下文)。然后你使用它:
var d = new Derived(4, 2);
d.foo(); // "I'm Base#foo, x = 4"
d.bar(); // "I'm Derived#bar, x = 4, y = 2"
Live example | source
在旧的代码,你有时会看到Derived.prototype
设立这样反而:
Derived.prototype = new Base();
......但有一个问题,做这样的说法:Base
可以做到每个实例的初始化这是不适合整个Derived
继承。它甚至可能需要参数(因为我们的Base
会;我们会通过x
?)。通过改为使Derived.prototype
成为由Base.prototype
支持的新对象,我们得到了正确的东西。然后我们从Derived
中调用Base
来获取每个实例的init。
以上是非常基本的,你可以看到涉及一些步骤。它也很少或根本没有使“超级电话”容易和高度维护。这就是为什么你会看到那么多“继承”脚本,比如Prototype的Class
,Dean Edwards的Base2或(咳嗽)我自己的Lineage
。
如果不能依靠在你的环境中ES5功能,并且不希望包括垫片,做的Object.create
的基础知识,你可以使用此功能在它的地方:
function simpleCreate(proto) {
function Ctor() {
}
ctor.prototype = proto;
return new Ctor();
}
然后,而不是
Derived.prototype = Object.create(Base.prototype);
你会怎么做:
Derived.prototype = simpleCreate(Base.prototype);
当然,你可以做更多的事情来自动化连接 —这基本上都是Lineage
。
...最后:上面我已经用于简单的匿名功能,例如:
Base.prototype.foo = function() {
// ...
};
...但我不这样做,在我真正的代码,因为I like to help my tools help me。所以我倾向于在每个“类”(构造函数和相关的原型)周围使用模块模式,并使用函数声明(因为我确实为web,IE7和IE8 still have problems使用了命名函数表达式。所以如果我不' T使用Lineage
,我会做上述这样的:
// Base
(function(target) {
// Base constructor
target.Base = Base;
function Base(x) {
// Base per-instance init
this.x = x;
}
// An example Base function
Base.prototype.foo = Base$foo;
function Base$foo() {
console.log("I'm Base#foo, x = " + this.x);
}
})(window);
// Derived
(function(target, base) {
// The Derived constructor function
target.Derived = Derived;
function Derived(x, y) {
// Init base
base.call(this, x);
// Derived per-instance init
this.y = y;
}
// Make the Derived.prototype be a new object backed up by the
// Base.prototype.
Derived.prototype = Object.create(base.prototype);
// Fix up the 'constructor' property
Derived.prototype.constructor = Derived;
// Add any Derived functions
Derived.prototype.bar = Derived$bar;
function Derived$bar() {
console.log("I'm Derived#bar, x = " + this.x + ", y = " + this.y);
}
})(window, Base);
...或者类似的东西Live copy | source
它的发生是因为没有在你的代码安排它*不*发生。如果你认为设置一个名为“base”的属性会使一个类继承另一个类,那么这是不正确的。 – Pointy
感谢格式化,@MarkLinus! – corazza
尝试将'Bla2.prototype'设置为'new Bla()'。 – Pointy