Подтвердить что ты не робот

OOP В javascript

Мне интересно, какой способ использования ООП в Javascript лучше всего подходит.

Существует эта прототипная вещь, и у вас есть стиль функции. Но у обоих есть очень плохие способы наследования базового класса.

Итак, я попытался создать способ сделать это возможным, не используя прототип и т.д.

function Car(name) {
    this.Name = name;

    this.FullName = function () {
        return this.Name;
    }
}

function SpecialCar(name, variant) {
    //BaseClass.apply(this, PARAMS AS ARRAY);
    Car.apply( this, [name] );

    //new property
    this.Variant = variant;

    //override function
    this.FullName = function () {
        return this.Name + " " + this.Variant ;
    }
}

var audi = new Car("audi");
$("#result").append(audi.FullName() + "<br>");

var audia3 = new SpecialCar("audi", "a3");
$("#result").append(audia3.FullName()+ "<br>");

Здесь вы можете проверить jsFiddle: http://jsfiddle.net/vu9ZF/2/

Это хорошо или это просто плохой практик?

Было бы очень приятно получить ответы на некоторые вопросы, почему другие способы лучше, потому что я просто не понимаю.

EDIT: Спасибо всем за то, что ответили на меня так быстро! Я пытался найти способ OOP в javascript для себя, не отвечая на вопрос о том, как сделать oop в javascript. Мне не нравится, как использовать прототип для этого, потому что я использую С# большую часть моего рабочего времени, и его немного запутывает переход между "С#-like oop" и "prototype oop". Но кто-то в комментариях сказал мне, что избежать прототипа не является хорошей идеей, soo плохое падение.

Спасибо stackoverflow your all awesome и спасли меня столько времени =)

4b9b3361

Ответ 1

Вот как это делается:

function Car ( name ) {
    this.name = name;
}

Car.prototype.fullName = function () {
    return this.name;
}

function SpecialCar ( name, variant ) {
    Car.apply( this, arguments );
    this.variant = variant;
}

SpecialCar.prototype = Object.create( Car.prototype );

SpecialCar.prototype.fullName = function () {
    return this.name + ' ' + this.variant;
}; 

(Для IE8 требуется прокладка Object.create)

Живая демонстрация: http://jsfiddle.net/3Rehr/


Итак, методы должны быть назначены объекту прототипа конструктора, а не самим экземплярам.

Кроме того, чтобы предварительно обработать экземпляр супер-конструктором, просто выполните следующее:

Car.apply( this, arguments );

поэтому this.base вещь не нужна.

Ответ 2

Это не особенно рекомендуется, потому что вы действительно возвращаете экземпляр Car, а не экземпляр SpecialCar.

audia3 instanceof Car === true;
audia3 instanceof SpecialCar === false;

Это запутанно, потому что вы выполняете new SpecialCar. Кроме того, свойства SpecialCar.prototype не будут доступны в экземпляре, но вы, похоже, используете собственный шаблон копирования наследования.

Ответ 3

Как я обычно делаю, это описывается на этой странице

Он дает коду более структурированную ссылку, даже мне нравится функция в вашем коде, позволяющая вызвать родительский конструктор.

function Car( name ) {
  this.Name = name;
}

Car.prototype.FullName = function FullName() {
  return this.Name;
}


function SpecialCar( name, variant ) {
  this.Name = name;
  this.Variant = variant;
}

SpecialCar.prototype = new Car();
SpecialCar.constructor = SpecialCar;

SpecialCar.prototype.FullName = function FullName() {
  return this.Name + " " + this.Variant; 
}

Ответ 4

Что касается шаблона конструктора, я предпочитаю ваш метод вместо использования apply или чего-то подобного. Это может немного запутать из-за необходимости return, но для меня это не кажется таким же грязным, как apply.

Тем не менее, я предпочитаю использовать прототипное наследование немного больше, с Object.create:

var Car = {
    fullName: function() {
        return this.name;
    }
}

var SpecialCar = Object.create(Car);
SpecialCar.fullName = function() {
    return this.name + ' ' + this.variant;
};

var audi = Object.create(Car);
audi.name = 'audi';

var audiA3 = Object.create(SpecialCar);
audiA3.name = 'audi';
audiA3.variant = 'A3';

Некоторые браузеры не поддерживают Object.create изначально, но он сжимается.

Ответ 5

Вот как я это сделаю. Нужен код сахара, чтобы он работал. Вы можете найти OoJs на github. OoJs покрывает большинство функций OOP из С++, за исключением множественного наследования и обеспечения чистых виртуальных функций...

;( function class_Car( namespace )
{
    'use strict';

    if( namespace.Car ) return    // protect against double inclusions

        namespace.Car = Car
    var Static        = TidBits.OoJs.setupClass( namespace, "Car" )


    // constructor
    //
    function Car( name )
    {
        this.Name = name               // data member, private by default

        return this.Public( FullName ) // method FullName will be public
    }


    function FullName()
    {
        return this.Name;
    }

})( window )




;( function class_SpecialCar( namespace )
{
    'use strict';

    if( namespace.SpecialCar ) return    // protect against double inclusions

        namespace.SpecialCar = SpecialCar
    var Static               = TidBits.OoJs.setupClass( namespace, "SpecialCar", "Car" )


    // constructor
    //
    function SpecialCar( name, variant )
    {
        this.Super( name )

        this.Variant = variant

        return this.Public( FullName )
    }


    function FullName()
    {
        return this.Car.FullName() + " " + this.Variant
    }

})( window )


var audi = new Car("audi");
$("#result").append(audi.FullName() + "<br>"); // output: audi

var audia3 = new SpecialCar("audi", "a3");
$("#result").append(audia3.FullName()+ "<br>"); // output: audi a3