Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Разбираем AjaxOOP (https://javascript.ru/forum/misc/12756-razbiraem-ajaxoop.html)

eai 01.11.2010 19:47

Разбираем AjaxOOP
 
Всем доброго времени суток.

Пересмотрев кучу библиотек для организации OOP на JavaScript более всего мне понравился синтаксис реализованный в библиотеке Ajax.OOP.

Беда в том, что
1. Проект закрыт судя по всему
2. Файл содержит еще кучу всякой лабуду для Ajax, которая и даром не нужна.

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

Поскольку не считаю себя супер профессионалом в JS то прошу помощи у сообщества в сем деле.

Предлагаю разбирать построчно анализировать код.

Вообщем основная функция которая создает класс это Ajax.Class

Предлагаю просто назвать ее _class

код выкладываю далее ...

eai 01.11.2010 19:49

чуть не забыл, понадобятся еще служебные функции.

в исходнике реализована функция $a которая используется по всей библиотеке. Нам интересна ее способность преобразовывать аргументы функции в массив. записал так
function args2array(obj)
{
	var al = obj.length;
	var args = new  Array(al);
	while (al--) 
		args[al] = obj[al];
	
	return args;
};


Еще есть функции проверяющие тип объекта.
Реализация их не очень интересна, однако для чистоты эксперимента выкладываю код тоже
Интерес вызывает isElement и isRegExp так как похоже для корректной работы потребуются дополнительные действия, но об этом позже.
function isElement(obj) 
{ 
	return (obj && obj.nodeType && obj.nodeType == 1) ? true : false; 
};
function isRegExp(obj) 
{ 
	return (obj && obj.constructor === RegExp); 
};
function isString(obj) 
{ 
	return (typeof obj == 'string'); 
};
function isNumber(obj) 
{ 
	return (typeof obj == 'number'); 
};
function isBoolean(obj) 
{ 
	return (typeof obj == 'boolean'); 
};
function isNull(obj) 
{ 
	return (obj === null); 
};
function isUndefined(obj) 
{ 
	return (obj === 'undefined' || obj === undefined || obj === 'unknown'); 
};
function isArray(obj) 
{ 
	return (obj && obj.constructor === Array); 
};
function isSimple(obj) 
{ 
	return (isString(obj) || isNumber(obj) || isBoolean(obj) || isRegExp( obj)); 
};
function isFunction(obj) 
{ 
	return (obj && obj.constructor === Function); 
};
function isObject(obj) 
{ 
	return (obj && !(isArray( obj) || isFunction( obj) || isSimple( obj))); 
};

B@rmaley.e><e 01.11.2010 20:05

Для проверки на регэксп должно хватить
alert( /inline regexp/ instanceof RegExp );
alert( new RegExp('regexp') instanceof RegExp );
alert( '/not regexp+?/' instanceof RegExp );

eai 01.11.2010 20:12

И далее сама функция _class
//получаем массив аргументов
var args = args2array(arguments);
var al = args.length;
// Если есть хотя бы 2 аргумента, значит первый это предок, запоминаем его и убираем из массива. Если предка нет, то он NULL
var parent = (al > 1 ? args.shift() : null);

// Получаем и запоминаем описание самого класса. Если такового нет, то пустое тело. Как и с предком убираем из массива аргументов тело класса.
var declaration = (args.shift() || {});

// Типа конструктор ;-)
var constructor = 'constructor';

// Проверяем правильный ли тип предка
if (parent && !isFunction(parent)) 
{
	throw new TypeError( 'in class definition - first argument is not a parent class constructor!');
}
// Проверяем является ли тело класса таковым
if (declaration && (!isObject(declaration) || 
						declaration == window || 
						declaration == document.body || 
						declaration == document || 
							isElement(declaration))) 
{
	throw new TypeError( 'in class definition - ' + (args.length > 1 ? 'second' : 'passed') + ' argument is not a class declaration object!');
}

// Собственно это и есть наш класс
var _class = function() 
{
	this[constructor].apply(this, args2array(arguments));
}

И тут начались проблемы с пониманием.
apply - вызов функции с массивом параметров
У свойства текущего контекста this[constructor] (фактически this['constructor']) вызывается (он сам по идее и вызывается) с передачей текущего контекста и оставшимися параметрами.
Что зачем почему не понятно.
// Пошло наследование свойств через прототип
if (parent) 
{ 
	var _parent = Function.blank;
	_parent.prototype = parent.prototype;
	_class.prototype  = new _parent;
}

1. Содается переменная функция временая _parent ей присваивается пустая функция (она определена в другом месте как пустая)
2. Prototype этой временной функции присваивается prototype предка.
3. Prototype нового создаваемого класса становться вновь созданный экзампляр временной функции (которая имеет тот же prototype что и предок)
// коли определены в текущем классе свойства, так соотвственно присвоить их, а коли они были в предке то переопределить.
// ну хак с конструктором для IE
if (declaration) 
{
	for (var property in declaration) 
	{
		_class.prototype[property] = declaration[property];
	}
	// line below is to fix bug with constructors in IE
	_class.prototype[constructor] = declaration[constructor] || Function.blank;
}

// этот кусок меня если четно не понятен. Особенно момент с возвратом прототипа пустой функции. Если честно не совсем понятно зачем создавать эти указатели на конструкторы ....
_class.prototype.$super  = parent ? parent.prototype : Function.blank.prototype;
_class.prototype.$_super = parent ? parent : Function.blank;
_class.prototype.$_self  = _class;

// собственно вернуть готовый класс
return _class;


Проанализировав код вдоль и поперек , не могу понять где тело конструктора мы присваиваем в _class
Судя по всему в теле должны быть только свойства и методы определены, а код не допускается. ;-)
Сложно выразился ... т.е. в теле любой код должен быть присвоением свойства или метода в синтаксисе
someProp: 10,
someMethod: function() {},

eai 01.11.2010 20:14

Цитата:

Сообщение от B@rmaley.e><e (Сообщение 76922)
Для проверки на регэксп должно хватить
alert( /inline regexp/ instanceof RegExp );
alert( new RegExp('regexp') instanceof RegExp );
alert( '/not regexp+?/' instanceof RegExp );

Ценное замечание, нужно будет включить в релиз

Kolyaj 01.11.2010 21:05

Может теорию сначала почитаете?

eai 01.11.2010 21:09

Цитата:

Сообщение от B@rmaley.e><e (Сообщение 76922)
Для проверки на регэксп должно хватить
alert( /inline regexp/ instanceof RegExp );
alert( new RegExp('regexp') instanceof RegExp );
alert( '/not regexp+?/' instanceof RegExp );

Цитата:

Сообщение от Kolyaj (Сообщение 76939)
Может теорию сначала почитаете?

Николая, не совсем понятно, кому вы это написали (при цитировании вашего сообщения получается что это ответ на сообщение Бармалея.

Если же все же это мне, то отвечу, читал я теорию и на этом сайте и на других, много и вдумчиво. Но поскольку нет идеологии или если хотите парадигмы ООП на JavaScript то вариантов много получается и почти все они построены на "хаках".

Kolyaj 01.11.2010 21:31

Цитата:

Сообщение от eai
Но поскольку нет идеологии или если хотите парадигмы ООП на JavaScript

Где её нет? В языке?

vladlen 02.11.2010 02:10

eai, прежде чем что-то утверждать прочтите это.
Смею вас уверить, что ваша коробка транзисторов, резисторов, дросселей и емкостей полностью построена на, как вы выразились, "хаках". Для примера: многопоточность и многоядерность. Везде применяются те или иные методы обхода проблемных мест.

eai 02.11.2010 08:40

Уф, я так и знал, что у меня будут сложности с пониманием в этом форуме. Ибо все же язык (общения) программиста на С++ всегда отличается людей которые работают на скриптовых языках. :)
Владлен, я не утверждал что нельзя использовать ООП на JS. Как вы можете заметить, я скорее наоборот всеми силами за.
Однако как я заметил и заметили другие члены сообщества в разных местах в интернете, нет , как бы это яснее выразиться ..., нативной что ли возможности использовать это.
Цитата:

Прототипное программирование
Прототипное программирование, сохранив часть черт ООП, отказалось от базовых понятий — класса и наследования.
В вами же присланной статье сие написано.

Предлагаю не спорить по этому вопросу, так как вопроса в сущности то нет.


Часовой пояс GMT +3, время: 07:50.