Ответ 1
Кажется, что
Bla2
не наследовал его из классаBla
!
Right. Вы ничего не сделали, чтобы подключить наследование там, вы только что создали член Bla2
, называемый 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
- от 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"
В более старом коде вы иногда видите Derived.prototype
следующим образом:
Derived.prototype = new Base();
... но есть проблема с этим: base
может выполнять инициализацию для каждого экземпляра, которая не подходит для полноты Derived
для наследования. Это может даже потребовать аргументы (как это делает наш base
, что мы будем передавать за x
?). Вместо того, чтобы сделать Derived.prototype
просто новым объектом, поддерживаемым Base.prototype
, мы получаем правильный материал. Затем мы вызываем base
из Derived
, чтобы получить 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() {
// ...
};
... но я не делаю этого в своем реальном коде, потому что Мне нравится помогать моим инструментам мне помочь. Поэтому я склонен использовать шаблон модуля вокруг каждого "класса" (функции конструктора и связанного с ним прототипа) и использовать объявления функций (поскольку я действительно работаю в Интернете, а IE7 и IE8 все еще имеют проблемы с именованными выражениями функций. Поэтому, если я не использовал 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);
... или что-то в этом роде. Живая копия | источник