似乎Bla2
没有继承它Bla
class!
正确的。你还没有做任何事情来连接继承,你只是创建了一个成员Bla2
called base
这是一个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 http://ecma-international.org/ecma-262/5.1/#sec-15.2.3.5来自 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"
实例 http://jsbin.com/ubikof | source http://jsbin.com/ubikof
在较旧的代码中,您有时会看到Derived.prototype
像这样设置:
Derived.prototype = new Base();
...但是这样做有一个问题:Base
可能会对每个实例进行初始化,这不适合整个实例Derived
继承。它甚至可能需要参数(如我们的Base
做;我们会认为什么是x
?)。通过改为使Derived.prototype
只是一个由Base.prototype
,我们得到了正确的东西。然后我们打电话Base
从内部Derived
获取每个实例的 init。
上面是非常基本的,正如您所看到的,涉及许多步骤。它也很少或根本没有使“超级调用”变得简单且高度可维护。这就是为什么你会看到这么多“继承”脚本,比如 Prototype 的Class
、迪恩·爱德华兹的 Base2,或(cough) my own Lineage http://code.google.com/p/lineagejs.
如果您不能依赖环境中的 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() {
// ...
};
...但我不会在我的真实代码中这样做,因为我喜欢帮助我的工具帮助我 http://blog.niftysnippets.org/2010/03/anonymouses-anonymous.html。所以我倾向于在每个“类”(构造函数和相关原型)周围使用模块模式并使用函数声明(因为我从事网络工作,并且 IE7 和 IE8还是有问题 http://blog.niftysnippets.org/2010/09/double-take.html具有命名函数表达式。所以如果我没有使用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);
...或类似的东西。实时复制 http://jsbin.com/ubikof/2 | source http://jsbin.com/ubikof/2/edit