JavaScript многоуровневое наследование

Я пытался получить голову вокруг наследования JavaScript. Смутно, кажется, существует много разных подходов - Crockford представляет довольно многих из тех, но не может вполне grok его проза (или возможно просто не удаются связать его с моим конкретным сценарием).

Вот пример того, что я имею до сих пор:

// base class
var Item = function( type, name ) {
    this.type = type;
    this.name = name; // unused
};

// actual class (one of many related alternatives)
var Book = function( title, author ) {
    this.name = title; // redundant (base class)
    this.author = author;
};
Book.prototype = new Item('book'); // duplication of "book"

// instances
var book = new Book('Hello World', 'A. Noob');

Этот подход оставляет меня с изрядной степенью избыточности, поскольку я не могу делегировать определенные для экземпляра атрибуты к базовому классу (во время опытного присвоения, значение атрибута неизвестно). Таким образом каждый подкласс должен повторить тот атрибут. Существует ли рекомендуемый способ решить это?

Вопрос о премии: существует ли разумный способ избежать "нового" оператора, или это рассматривалось бы как новичок, работающий против языка?

5
задан Bergi 8 June 2014 в 12:52
поделиться

3 ответа

Я покажу вам, как я достигаю таких вещей:-

 function Item(type, name)
 {
    if (arguments.length > 0)
    {
        this.type = type;
        this.name = name;
    }
 }

 function Book(title, author)
 {
   Item.call(this, "book", title);
   this.author = author;
 }
 Book.prototype = new Item();

Так что пару вещей, которые я делаю здесь, я пропускаю некоторый код инициализации в базовом классе, когда я обнаруживаю, что новый экземпляр создается просто как прототип.

Реальным средством, которое позволяет избежать дублирования, является использование Item.call в качестве конструктора базового класса. Это позволяет избежать дублирования в оригинале.

Что касается избежания нового , то будет полезно, если вы укажете, зачем вам это нужно? Однако, простой способ - добавить функцию в "функцию класса" напрямую, а не в прототип функции:-

Book.Create = function (title, author) { return new Book(title, author); }


var aBook = Book.Create("Code Complete 2", "Steve McConnell");

Хотя я вижу здесь небольшое преимущество.

3
ответ дан 14 December 2019 в 13:35
поделиться

Есть ли разумный способ избежать использования оператора «новый»

На самом деле вам нужно создать объект JavaScript, имеющий Item.prototype в цепочке прототипов. Но вы не хотите вызывать функцию конструктора Item , потому что это не имеет смысла: вы не создаете экземпляр Item, вы просто создаете подкласс.

Вы должны использовать new так или иначе, чтобы получить эту цепочку прототипов, но вам не нужно использовать Item для получения прототипа.Вы можете создать новую функцию, не являющуюся конструктором, с тем же прототипом, но без действия, которые базовые классы могут вызывать, когда они на самом деле не хотят создавать экземпляр объекта:

function Item(type) {
    this.type= type;
};

function Book(title, author) {
    Item.call(this, 'book');
    this.name= title;
    this.author = author;
};
function Item_nonconstructor() {}
Item_nonconstructor.prototype= Item.prototype;
Book.prototype= new Item_nonconstructor();

Вы можете сделать это немного менее уродливым в количество способов, например:

Function.prototype.subclass= function(base) {
    var c= Function.prototype.subclass.nonconstructor;
    c.prototype= base.prototype;
    this.prototype= new c();
};
Function.prototype.subclass.nonconstructor= function() {};

function Book(title, author) {
    Item.call(this, 'book');
    this.name= title;
    this.author = author;
};
Book.subclass(Item);

Или вы можете рассмотреть вопрос о перемещении вашего конструктора в функцию инициализатора или различные другие подходы. В JavaScript нет единой принятой системы классов / экземпляров. См. этот вопрос для подробного обсуждения объектных моделей JavaScript.

3
ответ дан 14 December 2019 в 13:35
поделиться

Мне тоже никогда не нравился базовый прототипный подход, у Джона Резига (крупнейшего автора jQuery) есть альтернативный подход, который я нашел гораздо более простым, легким и естественным, исходя из фона OO: Простое наследование JavaScript. Основываясь на ваших комментариях (те же самые мысли, что и у меня), я бы действительно посоветовал взглянуть.

Если тебе не нравится стиль, в котором ты находишься, и звучит так, как будто ты не , который тебе не нравится... рано меняешься. Есть несколько различных вариантов, редко когда-либо есть один способ сделать что-нибудь на javascript.

0
ответ дан 14 December 2019 в 13:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: