Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 05.10.2012, 10:39
Аспирант
Отправить личное сообщение для bFree Посмотреть профиль Найти все сообщения от bFree
 
Регистрация: 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;
}


Если кто-нибудь сможет подсказать, в чем косяк и где я туплю, то буду очень признателен. Не раз выручали меня уже на этом форуме.
Ответить с цитированием
  #2 (permalink)  
Старый 08.10.2012, 09:56
Аспирант
Отправить личное сообщение для bFree Посмотреть профиль Найти все сообщения от bFree
 
Регистрация: 19.08.2008
Сообщений: 42

Кажется, что никт оне поможет =(
Уже который день бьюсь и вообще не понимаю, что я делаю не так
Ответить с цитированием
  #3 (permalink)  
Старый 08.10.2012, 11:36
Аватар для Maxmaxmахimus
司会
Отправить личное сообщение для Maxmaxmахimus Посмотреть профиль Найти все сообщения от Maxmaxmахimus
 
Регистрация: 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.
Ответить с цитированием
  #4 (permalink)  
Старый 08.10.2012, 14:46
Аспирант
Отправить личное сообщение для bFree Посмотреть профиль Найти все сообщения от bFree
 
Регистрация: 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.
Ответить с цитированием
  #5 (permalink)  
Старый 08.10.2012, 14:57
Аватар для Maxmaxmахimus
司会
Отправить личное сообщение для Maxmaxmахimus Посмотреть профиль Найти все сообщения от Maxmaxmахimus
 
Регистрация: 29.02.2012
Сообщений: 198

Сообщение от bFree
Почему лучше использовать alert
Потому что консоль группирует однотипные выводы не проверяя особо их структуру, так и тут она подумала что эти обьекты одинаковые. и обьединила в один не смотря на то что значения свойств у них разные. это типа оптимизация у неё такая. алерт просто показал РЕАЛЬНОЕ положение вешей.


Сообщение от bFree
Почему лучше использовать Class ?
Функция класс не эмулирует ООП поведение других языков, и названа так лишь по аналогии. Её можно назвать и Extends. Она является лишь удобной оберткой над прототипным наследованием. Седня напишу топик про неё (модераторы удалили видимо случайно)


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

иными словами логер глючный



П.С метод setOptions не обязательно было лписывать отдельно))) можно было прямо в констуркторе описать то что он делает)) потому что конструктор тоже наследуется (как ты заметил).
Метод который вызывается при создании обьектов (this.__construct__) наследуется дочерним "классам" ))
.ну да ладно, это кому как удобнее ))

Последний раз редактировалось Maxmaxmахimus, 08.10.2012 в 15:04.
Ответить с цитированием
  #6 (permalink)  
Старый 08.10.2012, 15:02
Аспирант
Отправить личное сообщение для bFree Посмотреть профиль Найти все сообщения от bFree
 
Регистрация: 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
Ответить с цитированием
  #7 (permalink)  
Старый 08.10.2012, 15:05
Аватар для Maxmaxmахimus
司会
Отправить личное сообщение для Maxmaxmахimus Посмотреть профиль Найти все сообщения от Maxmaxmахimus
 
Регистрация: 29.02.2012
Сообщений: 198

да что ты будешь делать )) щас напишу
Ответить с цитированием
  #8 (permalink)  
Старый 08.10.2012, 15:07
Аспирант
Отправить личное сообщение для bFree Посмотреть профиль Найти все сообщения от bFree
 
Регистрация: 19.08.2008
Сообщений: 42

Цитата:
П.С метод setOptions не обязательно было лписывать отдельно))) можно было прямо в констуркторе описать то что он делает)) потому что конструктор тоже наследуется (как ты заметил).
Метод который вызывается при создании обьектов (this.__construct__) наследуется дочерним "классам" ))
.ну да ладно, это кому как удобнее ))
Это сделал для того, чтобы во внешнем коде мог менять опции.
Да и это просто пример. Понятное дело, что в setOptions могут быть какие-то объемные вещи, которые незачем пихать в конструктор.

Последний раз редактировалось bFree, 08.10.2012 в 15:10.
Ответить с цитированием
  #9 (permalink)  
Старый 08.10.2012, 15:11
Аспирант
Отправить личное сообщение для bFree Посмотреть профиль Найти все сообщения от bFree
 
Регистрация: 19.08.2008
Сообщений: 42

Ииии.. ваш вариант так же не работает =(
Ответить с цитированием
  #10 (permalink)  
Старый 08.10.2012, 15:12
Аватар для Maxmaxmахimus
司会
Отправить личное сообщение для Maxmaxmахimus Посмотреть профиль Найти все сообщения от Maxmaxmахimus
 
Регистрация: 29.02.2012
Сообщений: 198

секунду))
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Прототипы в JS Harvey Общие вопросы Javascript 3 06.12.2011 11:00
Как смотреть данные добавлены к объекты через data()? TicTac jQuery 4 04.05.2011 08:48
Что такое прототипы Deniskan Общие вопросы Javascript 7 03.08.2010 16:06
Объекты в массиве. delias Общие вопросы Javascript 2 21.04.2010 22:28