Объекты не наследуют прототипированные функции

У меня есть одна функция конструктора, которая действует как суперкласс:

Bla = function(a){this.a = a;}

Я прототипирую это, чтобы включить простой метод:

Bla.prototype.f = function(){console.log("f");

А теперь новыйBla(1).f(); будет регистрировать & quot; f & quot; в консоли. Но, допустим, мне нужен подкласс, который наследуется от Bla:

Bla2 = function(a)
{
    this.base = Bla;
    this.base();
}

x = new Bla2(5);

Теперь, как и ожидалось,x.a дает мне5, Но,x.f являетсяundefined! Похоже наBla2 не унаследовал его отBla учебный класс! Почему это происходит и как мне это исправить?

 Pointy17 июн. 2012 г., 18:16
@ T.J.Crowder да, я понимаю это; Вы, как обычно, дали исчерпывающий ответ :-) Я так редко пишу такой код, что не доверяю себе, чтобы попытаться получить реальный ответ.
 Pointy17 июн. 2012 г., 17:42
Попробуйте установитьBla2.prototype вnew Bla().
 corazza17 июн. 2012 г., 17:41
Спасибо за форматирование, @MarkLinus!
 Pointy17 июн. 2012 г., 17:41
Это происходит потому, что в вашем коде ничего не устраиваетnot произойдет. Если вы думаете, что устанавливаете свойство под названием «base» делает один класс наследуемым от другого, что неверно.
 corazza17 июн. 2012 г., 17:43
Хорошо, но вызов базы должен установить «это» в функции конструктора, чтобы указать на мой объект, верно? Ну тогда как мне сделать это правильно?

Ответы на вопрос(1)

Решение Вопроса

Seems like Bla2 didn't inherit it from the Bla class!

Правильно. Вы ничего не сделали для подключения наследства, вы только что создали члена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 чтобы получить инициализацию для каждого экземпляра.

Вышесказанное является очень простым и, как вы можете видеть, включает в себя ряд шагов. Он также мало или ничего не делает, чтобы сделать "суперзвезды" простой и легко обслуживаемый. Вот почему вы видите так много «наследства». сценарии, такие как прототипыClassДин Эдвардс Base2, или(cough) мой собственный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);

Конечно, вы можете сделать больше, чтобы автоматизировать подключение & # xA0; & # x2014; что всеLineage в основном делает.

... и наконец: выше я использовал анонимные функции для простоты, например:

Base.prototype.foo = function() {
    // ...
};

... но я не делаю этого в моем реальном коде, потому чтоМне нравится помогать моим инструментам помогать мне, Поэтому я склонен использовать шаблон модуля вокруг каждого «класса» (функция конструктора и связанный с ней прототип) и использовать функциюdeclarations (так как я работаю для Интернета, и 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);

...или что-то типа того.Живая копия | источник

 20 июн. 2012 г., 19:23
красиво структурированный, очень информативный ответ. +1

Ваш ответ на вопрос