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 и спасли меня столько времени =)
Ответы
Ответ 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