ООП В JavaScript - PullRequest
       6

ООП В JavaScript

4 голосов
/ 23 февраля 2012

Мне интересно, какой способ использования ООП в 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/

Это нормально или это просто плохая практика?

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

РЕДАКТИРОВАТЬ: Спасибо всем за быстрый ответ! Я пытался найти какой-то способ ООП в javascript для себя, не отвечая о том, как сделать ООП в javascript. Мне не нравится способ использования прототипа для этого, потому что я использую c # большую часть своего рабочего времени, и это немного сбивает с толку переключаться между "c #-like oop" и "prototype oop". Но кто-то в комментариях сказал мне, что избегать прототипа - не очень хорошая идея, так что оставьте это.

Спасибо stackoverflow, вы все потрясающе и сэкономили мне столько времени =)

Ответы [ 5 ]

4 голосов
/ 23 февраля 2012

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

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;
}; 

(вам нужно подложить Object.create для IE8)

Демо: http://jsfiddle.net/3Rehr/


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

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

Car.apply( this, arguments );

так что this.base вещь не нужна.

3 голосов
/ 23 февраля 2012

Обычно я иду так, как описано на этой странице

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

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; 
}
3 голосов
/ 23 февраля 2012

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

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

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

2 голосов
/ 23 февраля 2012

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

1 голос
/ 14 августа 2013

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

;( 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...