оцените такой подход создания классов
Сабж. Насколько такой подход уместен в JS? Какие могут быть проблемы?
var popupObject = { // URL обработчика url: null, // Данные для запроса data: {}, // Функция, которая будет выполнена в случае выполнения запроса success: function(data, textStatus, jqXHR){ // Пустая функция, не надо сюда ничего писать }, /** * Конструктор объекта. * * @param string url путь к обработчику запроса * @param object data данные для запроса * @param function success функция, которая выполнится в случае выполнения запроса * @return object this */ constuctor: function(url, data, success){ this.url = url; this.data = data !== undefined ? data : this.data; this.success = success !== undefined ? success : this.success; return this; }, /** * Основной метод, выполняющий запрос, прорисовывающий данные из ответа и * исполняющий метод success */ run: function() { $j.ajax({ type: "POST", url: this.url, data: this.data, cache: false, context: this, success: function(data, textStatus, jqXHR){ if (data.status.toLowerCase() === 'ok') { this.embed(data); this.success(data, textStatus, jqXHR); } else { if (window.console && window.console.log) { // console.log(data); } } } }); }, /** * Метод, выполняющий вставку данных из ответа куда-либо. * В нашем случае - в попап. * Данный метод можно перегрузить и вставлять данные куда угодно, в любое мето в DOM-дереве. * * @param array data response данные */ embed: function(data) { var unique_id = 'unique_' + this.rand(); var full_id = unique_id + '_for_popup'; $j('<div id="' + full_id + '" style="display:none"></div>').appendTo('body').append(data.content); openStaticPopup(unique_id); $j('#' + full_id).remove(); }, rand: function() { return Math.floor(Math.random() * 1000); } }; |
Василий Б., и как этим пользоваться?
|
danik.js,
success = function(data){ // функция исполнится после успешного выполнения ajax запроса, аналог success в API jQuery } var popup = popupObject.constuctor('/ajax/popup_delivery.php', {id: 123}, success); popup.run(); // или popupObject.constuctor('/ajax/popup_delivery.php', {id: 123}, success).run(); типа того. просто как пример класса, что он делает - не так уж и важно (получает html из json и рендит его либо в попап, либо в любое место в DOM структуре). Меня просто интересовало, подобный подход чем-то отличается от подхода, когда мы объявляем функцию со свойствами и методами через this, вот так: function foo() { this.var1 = 123; this.bar = function(){ // do } } |
А каким боком это класс? Как можно создать два экземпляра этого класса?
|
ага, ща допишем...
|
Цитата:
создавать экземпляры нельзя, но вот наследовать его можно : var popupMastaa = Object.create(popupObject); вуаля, у нас есть новый объект, прототипом которого является popupObject. |
Вот только нафига метод constructor. Какой же это конструктор.
|
melky,
а что должно быть в create методе? Чисто так, для любопытства спрашиваю.. Назначить прототипом Object мой объект popupObject? Цитата:
/** * Конструктор объекта. * * @param string url путь к обработчику запроса * @param object data данные для запроса * @param function success функция, которая выполнится в случае выполнения запроса * @return object this */ constuctor: function(url, data, success){ this.url = url; this.data = data !== undefined ? data : this.data; this.success = success !== undefined ? success : this.success; // Поскольку в JS нет классов, то мы создаем копию данного объекта (this) // и возвращаем его, что бы иметь возможность создавать несколько экземпляров объекта popupObject. var o = new Object(); for (var i in this) { if (this.hasOwnProperty(i)) { o[i] = this[i]; } } return o; }, и это работает, я пробовал создать два класса с разными параметрами. Ура! Только я от не понял одного - я пытался изначально написать код клонирования объекта так: var o = new Object(); for (var i in this) { if (this.hasOwnProperty(i)) { console.log(i + ' ' + this.i); } } вот что мне выдало в консоли: Цитата:
this.i- undefined. В упор не понимаю, почему так происходит. По идее, в i у меня содержится имя свойства. Почему я через точку не могу получить доступ к свойствам? |
Цитата:
Цитата:
Вопрос - с какой целью ты пытаешься изобрести классы? Ради экспериментов? Или свято веришь что что-то изобретешь новое? Или просто не знаешь основ JS и пытаешься по не знанию создать свой велосипед? Цитата:
|
Цитата:
что значит постоянно изменяться? я создаю отдельный объект с какими-то свойствами. с помощью клонирования объекта я могу создать два разных объекта, у них разные свойства. это то, что мне нужно - эмуляция классов. Вопрос - с какой целью ты пытаешься изобрести классы?ради удобства разработки. да я и не пытаюсь изобрести классы. |
var popup = popupObject.constuctor('/ajax/popup_delivery.php', {id: 123}, success);
console.log(popupObject.url); // что выдаст? Зачем это свойство хранится? Цитата:
|
Цитата:
function foo() { this.prop = ... } ? Цитата:
popupObject.constructor(...) Вы что предлагаете? Сделать "uset" или.. вообще не писать в popupObject? Вот так: constuctor: function(url, data, success){ // Поскольку в JS нет классов, то мы создаем копию данного объекта (this) // и возвращаем его, что бы иметь возможность создавать несколько экземпляров объекта popupObject. var o = new Object(); for (var i in this) { if (this.hasOwnProperty(i)) { o[i] = this[i]; } } // свойства назначаем только конкретному объекту o.url = url; o.data = data !== undefined ? data : this.data; o.success = success !== undefined ? success : this.success; return o; },Так? |
Цитата:
это ... как из дивана пытаться делать завод по изготовлению мебели. надеюсь, меня поняли :) Цитата:
рекомендую открыть learn.javascript.ru и почитать про способы создание объектов ... там уже есть вся инфа :) Цитата:
Цитата:
еще раз рекомендую открыть learn.javascript.ru :) function Blah () { } var myBlah = new Blah(); |
да читал я 20 раз это все уже. меня интересует оптимальный подход создания объектов а-ля класс.
Конструкторы мне не нравятся. Они не логичны что ли... вот я на конструкторе писал класс для работы с Аякс: function Ajax() { /** * Экземпляр XMLHttpRequest. * * @access private * @var object XMLHttpRequest */ var req; /** * HTTP-заголовки * * @access private * @var array */ var httpHeaders = {"If-Modified-Since" : "Sat, 1 Jan 2000 00:00:00 GMT"} /** * Описания статусов readyState * * @access private * @var array */ var statuses = ['Не инициализиован', 'Метод open() вызван, запрос не отправлен', 'Запрос был передан', 'Ответ сервера принят частично', 'Данные приняты, соединение закрыто']; this.addUniqueQS = false; /** * Создает объект XMLHttpRequest * * @param void * @return XMLHttpRequest|null */ (function() { if (window.XMLHttpRequest) { try { req = new XMLHttpRequest(); } catch (e){} } // only IE 6 =< else if (window.ActiveXObject) { try { var aVersions = ["MSXML2.XMLHttp.5.0", "MSXML2.XMLHttp.4.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp", "Msxml2.XMLHTTP", 'Microsoft.XMLHTTP']; for (var j in aVersions) { try { req = new ActiveXObject(aVersions[j]); break; } catch (e){} } } catch (e){} } if (!req) { throw new Krugozor_Exception(_CONFIG.messages[_CONFIG.lang].ajax.xmlhttprequest_not_found); } })(); /** * Метод принимает в качестве аргумента анонимную функцию, * которая привязывается к обработчику onreadystatechange. * Функция должна иметь интерфейс для принятия двух объектов: * - первый объект - ссылка на Ajax объект * - второй объект - ссылка на объект xmlHttpRequest * * @param object * @return void */ this.setObserverState = function(observer_function) { var ajax_object = this; var req_object = req; this.observerState = function() { if (req_object.readyState == 4) { if (req_object.status == 200) { observer_function(ajax_object, this); } } } return this; } /** * Абстрактный предопределяемый метод, привязанный * к обработчику onreadystatechange. * Пример предопределения в клиентском скрипте: * * var ajax = new Ajax(); * ajax.observerState = function() * { * if (ajax.getHttpRequest().readyState == 4) { * if (ajax.getHttpRequest().status == 200) * { * alert(ajax.getHttpRequest().responseText) * } * } * } * * @param void * @return mixed */ this.observerState = function() { if (req.readyState == 4) { if (req.status == 200) { alert('Метод observerState должен быть предопределен перед использованием объекта'); } } } /** * Отправляет GET-запрос по адресу url * * @param string url * @param boolean синхронность запроса. * true - асинхронный, false - синхронный * @return void */ this.get = function(url, synchronicity) { if (arguments.length == 1) { synchronicity = true; } if (!!this.addUniqueQS) { url += (url.indexOf('?') == -1 ? '?' : '&') + Math.floor(Math.random()*1000); } req.open('GET', url, !!synchronicity); this.sendHeaders(); if (synchronicity) { req.onreadystatechange = this.observerState; } req.send(null); return this; } /** * Устанавилвает заголовок HTTP с ключом key * и значением value. * * @access public * @param key имя HTTP-заголовка * @param value значение HTTP-заголовка * @return void */ this.setHeader = function(key, value) { httpHeaders[key] = value; } /** * Отправляет HTTP-заголовки. * * @access private * @param void * @return void */ this.sendHeaders = function() { for (var i in httpHeaders) { if (typeof httpHeaders[i] == 'string') { req.setRequestHeader(i, httpHeaders[i]); } } } /* Методы получения ответа (XMLHttpRequest) и результата из ответа */ /** * Возвращает экземпляр объекта XMLHttpRequest * * @param void * @return object req */ this.getHttpRequest = function() { return req; } /** * Возвращает статус HTTP * * @param void * @return int */ this.getStatus = function() { return req.status; } /** * Возвращает стандартный объект JS, который является * "сериализованным" объектом в виде строки текста ответа - JSON. * * @access public * @param void * @return object */ this.getJson2HashByKey = function() { return eval( "(" + req.responseText + ")" ); } /** * Возвращает текст ответа сервера * * @access public * @param void * @return string */ this.getText = function() { return req.responseText; } } Пример использования: // Для асинхронных запросов: var async_ajax = new Ajax(); async_ajax.setObserverState( function(ajx, xhr) { alert( ajx.getJson2HashByKey() + ' ' + xhr.responseText); } ).get("/ajax/country"); Ещё один способ пробовал, но это я так понимаю jQuery стиль и это сингелтон: var click = (function(){ var prop = '...'; var method = function(){ // do it } return { init: method } })(); var myClick = click.init();и т.д. Этот способ по вашему лучше, чем описанный в первом посте? |
Цитата:
в JavaScript прототипное программирование... а это значит, что вы должны писать таким способом, и более пока никак идти против языка нет смысла - только добавит тормозов конечно, можно заюзать библиотеки для облегчения объектного программирования, но это уже сами :) |
melky,
Цитата:
Я кажется понимаю что такое прототип и чем он отличается от свойства объекта: function Base(){ this.f11 = function(){alert('call Base::f11')} }; Base.prototype.f1 = function(){alert('call Base::f1');} function Parent(){ this.f11 = function(){alert('call Parent::f11')} } Parent.prototype.f1 = function(){alert('call Parent::f1')} Parent.prototype = new Base(); var o = new Parent(); o.f1(); // `call Base::f1` - перезагрузили Parent::f1 методом из прототипа Base? o.f11(); // `call Parent::f11` - перезагрузки не произошло, т.к. ф-ия f11() - свойство объекта, а не прототипа правильно ли я понимаю отличие прототипа от свойства объекта? |
Это один и тот же подход. Просто в конструкторе нужно назначать свойства экземпляра (личные), а в прототипе - свойства прототипа (обычно методы). Почитай хотя бы http://learn.javascript.ru/prototype
|
danik.js,
как из можно назвать личными, если function Base(){ this.f = function(){alert('Base::f')} }; function Parent(){} Parent.prototype = new Base(); (new Parent()).f(); метол f доступен в Parent! Не могу понять почему.. метод f - это свойство объекта Parent, а не прототипа Base? |
Под "личными" я не имел ввиду private. Я имел ввиду принадлежащие экземпляру.
Цитата:
|
danik.js,
да читал я материал, читал! Там написано следующее: Цитата:
Цитата:
Свойства ищутся в прототипе объекта. Правильно ли я понимаю, что только при использовании new в дочерний объект подтягиваются ВСЕ свойства объекта-прототипа? Base = function(){}; Parent = function(){}; Parent.prototype = new Base(); var o = new Parent(); Base.func_as_prop = function(){}; Base.prototype.func_in_proto = function(){}; console.log(o.func_as_prop); // undefined - в объекте o нет свойства, т.к. оно не было подтянуто конструктором console.log(o.func_in_proto); // function console.log(Base.func_as_prop); // function console.log(Base.func_in_proto); // почему undefined? почему не ищет в своем прототипе? |
Цитата:
в ES5 добавили возможность смотреть на них, и управлять ими Object.getOwnPropertyDescriptor({ "foo": "bar" }, "foo"); // удобнее смотреть в консоли разработчика ссылка на MDN как видим, нет параметра "наследуемый", т.е. все свойства в объектах JavaScript по умолчанию публичные. поэтому мы их видим, когда присваиваем прототипу одного объекта другой. |
Цитата:
Вобще, открой консоль, накалякай там ченибудь да поизучай объекты. Я использую Chrome, там консоль как мне кажется самая удачная. |
Часовой пояс GMT +3, время: 05:46. |