05.10.2012, 10:39
|
Аспирант
|
|
Регистрация: 19.08.2008
Сообщений: 42
|
|
Объекты, прототипы и циклы
Здравствуйте!
Решил применять прототипное наследование. Столкнулся с не совсем очевидным для меня косяком. Сразу приведу иллюстрирующий пример кода:
// Базовый объект
function Foo(options) {
this.setOptions(options);
}
Foo.prototype.defaultOptions = {
some_option: null
};
Foo.prototype.setOptions = function(options) {
this.options = jQuery.extend(true, this.defaultOptions, options);
};
// Наследник
function Bar(options) {
this.setOptions(options);
}
extend(Bar, Foo);
// Добавим какие-то свои опции
Bar.prototype.defaultOptions = {
some_option : null,
another_option: false
};
// Создадим несолько объектов
for(var i = 0; i < 4; i++) {
var obj = new Bar({
some_option: i,
another_option: true
});
console.log(obj.options); // откроем каждую строку в Firebug'е и везде some_option будет равно 3 =(
}
В примере я использовал функцию extend из уроков с javascript.ru. Вот она:
function extend(Child, Parent) {
var F = function() {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.superclass = Parent.prototype;
}
Если кто-нибудь сможет подсказать, в чем косяк и где я туплю, то буду очень признателен. Не раз выручали меня уже на этом форуме.
|
|
08.10.2012, 09:56
|
Аспирант
|
|
Регистрация: 19.08.2008
Сообщений: 42
|
|
Кажется, что никт оне поможет =(
Уже который день бьюсь и вообще не понимаю, что я делаю не так
|
|
08.10.2012, 11:36
|
|
司会
|
|
Регистрация: 29.02.2012
Сообщений: 198
|
|
во первых сделай то же самое алертом
alert( obj.options.some_option )
во вторых для наследования используй общеизвестную функцию Class, и с ней твой код будет выглядить так
п.с. в this.__construct__ описывается конструктор
// родитель
var Foo = new Class( function () {
this.__construct__ = function ( options ) {
this.options = jQuery.extend( true, this.defaultOptions, options );
};
this.defaultOptions = {
some_option:'foo_defoult'
};
} );
// наследник ( в настеднике пишем только различия от родителя, либо добавляем что-то новое )
var Bar = new Class( Foo, function () {
this.defaultOptions = {
some_option:'bar_defoult'
};
} );
и собственно сама функция
function Class( a, b ) {
var description = b || a,
superClass = b ? a : null,
overname = Class.overname || 'super',
Constructor = (description.name)
? eval( "(function " + description.name +
"(){ if ( this.__construct__ ) return this.__construct__.apply( this, arguments )})" )
: function () {
if ( this.__construct__ ) return this.__construct__.apply( this, arguments )
},
Object = function Object() {
};
Object.prototype = superClass ? superClass.prototype : Class.prototype;
description.prototype = new Object;
Constructor.prototype = new description( Constructor, description.prototype );
var obj = Constructor.prototype;
for ( var key in obj ) {
if ( obj.hasOwnProperty( key ) && obj[key] instanceof Function ) {
var parentProperty = description.prototype[key];
if ( parentProperty )
(function ( originalMethod, parentMethod, key ) {
obj[key] = function () {
var bk = this[overname];
this[overname] = parentMethod;
var returns = originalMethod.apply( this, arguments );
if ( bk ) this[overname] = bk;
else delete this[overname];
return returns;
}
})( obj[key], parentProperty, key )
}
}
Constructor.create = function ( args ) {
function Object() {
if ( this.__construct__ ) return this.__construct__.apply( this, args )
}
Object.prototype = Constructor.prototype;
return new Object
};
return Constructor;
}
Где то был топик рассказывающий как её использовать, поищу, если не найду новый напишу.
Последний раз редактировалось Maxmaxmахimus, 08.10.2012 в 11:56.
|
|
08.10.2012, 14:46
|
Аспирант
|
|
Регистрация: 19.08.2008
Сообщений: 42
|
|
Спасибо за наводку!
Появились вопросы:
Почему лучше использовать alert (кроме того, что он прерывает работу скрипта)?
Почему лучше использовать Class ? Все, что я читал про наследование в JS сводилось к тому, что незачем пытаться эмулировать классы, как в других ЯП, а лучше использовать прототипы, ибо для этого язык и задуман.
Также, к сожалению, код работать не начал =(
// Базовый объект
var Foo = new Class(function(options) {
this.__construct__ = function(options) {
this.setOptions(options);
};
this.defaultOptions = {
some_option: null
};
this.setOptions = function(options) {
this.options = jQuery.extend(true, this.defaultOptions, options);
};
});
// Наследник
var Bar = new Class(Foo, function(options) {
this.defaultOptions = {
some_option : null,
another_option: false
}
});
var objs = [];
// Создадим несолько объектов
for(var i = 0; i < 4; i++) {
objs.push(new Bar({
some_option: i,
another_option: true
}));
}
console.log(objs[1].options); // some_option = 3 (почему!?)
console.log(objs[3].options); // some_option = 3 (так и должно быть)
Последний раз редактировалось bFree, 08.10.2012 в 14:56.
|
|
08.10.2012, 14:57
|
|
司会
|
|
Регистрация: 29.02.2012
Сообщений: 198
|
|
Сообщение от bFree
|
Почему лучше использовать alert
|
Потому что консоль группирует однотипные выводы не проверяя особо их структуру, так и тут она подумала что эти обьекты одинаковые. и обьединила в один не смотря на то что значения свойств у них разные. это типа оптимизация у неё такая. алерт просто показал РЕАЛЬНОЕ положение вешей.
Сообщение от bFree
|
Почему лучше использовать Class ?
|
Функция класс не эмулирует ООП поведение других языков, и названа так лишь по аналогии. Её можно назвать и Extends. Она является лишь удобной оберткой над прототипным наследованием. Седня напишу топик про неё (модераторы удалили видимо случайно)
Сообщение от bFree
|
Также, к сожалению, код работать не начал =(
|
Твой код и работал до этого, прблема в оптимизации логера консоли. о чем я уже говорил выше)
иными словами логер глючный
П.С метод setOptions не обязательно было лписывать отдельно))) можно было прямо в констуркторе описать то что он делает)) потому что конструктор тоже наследуется (как ты заметил).
Метод который вызывается при создании обьектов ( this.__construct__) наследуется дочерним "классам" ))
.ну да ладно, это кому как удобнее ))
Последний раз редактировалось Maxmaxmахimus, 08.10.2012 в 15:04.
|
|
08.10.2012, 15:02
|
Аспирант
|
|
Регистрация: 19.08.2008
Сообщений: 42
|
|
Maxmaxmахimus, спасибо за разъяснение!
Но, к сожалению, с алертами ситуация не исправилась =(
var objs = [];
// Создадим несолько объектов
for(var i = 0; i < 4; i++) {
objs.push(new Bar({
some_option: i,
another_option: true
}));
}
alert(objs[1].options.some_option); // some_option = 3 =(
alert(objs[3].options.some_option); // some_options = 3
|
|
08.10.2012, 15:05
|
|
司会
|
|
Регистрация: 29.02.2012
Сообщений: 198
|
|
да что ты будешь делать )) щас напишу
|
|
08.10.2012, 15:07
|
Аспирант
|
|
Регистрация: 19.08.2008
Сообщений: 42
|
|
Цитата:
|
П.С метод setOptions не обязательно было лписывать отдельно))) можно было прямо в констуркторе описать то что он делает)) потому что конструктор тоже наследуется (как ты заметил).
Метод который вызывается при создании обьектов (this.__construct__) наследуется дочерним "классам" ))
.ну да ладно, это кому как удобнее ))
|
Это сделал для того, чтобы во внешнем коде мог менять опции.
Да и это просто пример. Понятное дело, что в setOptions могут быть какие-то объемные вещи, которые незачем пихать в конструктор.
Последний раз редактировалось bFree, 08.10.2012 в 15:10.
|
|
08.10.2012, 15:11
|
Аспирант
|
|
Регистрация: 19.08.2008
Сообщений: 42
|
|
Ииии.. ваш вариант так же не работает =(
|
|
08.10.2012, 15:12
|
|
司会
|
|
Регистрация: 29.02.2012
Сообщений: 198
|
|
секунду))
|
|
|
|