Как стать автором
Обновить

Комментарии 73

Замечательно.
Всего 2 "но":
- не заметил ссылки на весь пакет utils.js
- Хабр бьёт ссылку для Source Code Highlighter, может вовсе убрать?
ну для этого есть ctrl-c ctrl-v
Да, я слышал что-то про эти хоткеи :)
Но с исходным файлом было бы более хабраюзерфрендли.
НЛО прилетело и опубликовало эту надпись здесь
в чём преимущество перед jQuery, например ?
jQuery, например, не обеспечивает механизмами наследования, а лишь позволяет расширять самого себя.
Я вот пользуюсь jQuery, но всё равно написал свой механизм наследования для организации компонентов. Правда при этом активно использовал некоторые механизмы от самого jQuery, которые выполняют много полезной рутины.

А автору спасибо за хорошую статью. Довольно популярно написано. Кое-что интересное я для себя выцепил.
:)) Спасибо, сам с усами, доки читать умею. Именно этот метод из jQuery я и использовал для реализации нормального наследования. Однако наследование в полноценном ООП, это не тупое дописывание свойств объекта (чем и занимается этот метод), это нечто большее.
Ну а JavaScript-не полноценный ООП - это вообще объектно-прототипный язык. И с определенных пор, мы, например, не используем для наследования внетренние механизмы каких-нибудь библиотек просто для того, чтобы быть чуть более независимыми от библиотеки (т.к. часто приходится использовать по нескольку разных сразу).
А функция extend есть в любом JS-framework'е.

Кстати, наследование "в виде, похожем на ООП" реализовано в MooTools, со всеми "new Class", "Class.extend" и "Class.implement".

А вообще - незачем изобретать велик.
Пора уже забыть про "классы" и начать думать прототипами.
Думается мне, что большинство пользуется популярными javascript-фреймворками и написанием подобного кода никто не занимается.
Не всегда. Иногда необходим определенной функционал, для которого использование фрэймворка просто трата ресурсов клиента на инициализацию самого фрэймворка. В подходе со своими либами можно на ходу выкинуть все что не используется. Кстати по 3 пункту клонирования. Не получится точной копии, хотя бы по тому, что многие проверки на тип объекта учитывают свойство length которое "неожиданно" начнет там присутствовать и наверное быть равным нулю. Таким образом выдадут что это список.
Немного поправлюсь, есть еще и instanceof который гарантированно скажет что это список
только если не передавать его между фреймами...
Как говорится, зачем использовать Камаз со множеством функций, чтобы перевезти человека из точки А в В, и при этом терять в скорости осуществления поставленной цели.
Вот только Вы потеряете в скорости осуществления целей в процессе изучения этой библиотеки и напарывания на грабли, которые там скорее всего есть.
даже не обязательно нулю, в следующем примере - четырем

var z = {'3' : 'bla-bla'}
var x = []
for(name in z)
x[name] = z[name]
alert(x.length)
НЛО прилетело и опубликовало эту надпись здесь
мде.. не нашел ни одной полезной..
7.пункт ... последняя строчка
"для меньшей скорости исполнения" - зачем скорость уменьшать?
Помоему "node.innerHTML = '';" будет работать куда быстрее чем фуркция removeChildrenRecursively.
«Занэймспейсить» бы всё это добро. Очень неоптимально написано вцелом. Например:
document.getElementById(nodeId).parentNode.removeChild(document.getElementById(nodeId));
не вижу смысла использовать велосипеды, а не фреймворки поддерживаемые большими сообществами.
может пригодиться только в частных случаях.
кто-то ещё игнорирует namespace в своих библиотеках?
Слово "Позиционирование", мне кажется, пишется с одним "и", а не как "позицИИонирование"
Функция cloneObj не отработает правильно, если у клонируемого объекта есть свойство содержащее объект.
Мне больше нравится вот такой вариант:

function clone(o) {
if(!o || ‘object’ !== typeof o) {
return o;
}
varc = ‘function’ === typeof o.pop ? [] : {};
var p, v;
for(p in o) {
if(o.hasOwnProperty(p)) {
v = o[p];
if(v && ‘object’ === typeof v) {
c[p] = clone(v);
}
else {
c[p] = v;
}
}
}
return c;
}

Взято отсюда: http://snowcore.net/clone-javascript-obj…
var o= {};
o.o= o;
Здесь вообще вопрос не о функциях, а, по сути, об организации и поддержке собственного JS-фреймворка.

Здесь еще сотни неучтенных моментов, которые есть во фреймворках, которые при этом:
- Написаны качественно (это важно);
- Поддерживаются независимо от вас другими специалистами очень высокого уровня;

Поддерживать свой недо-framework смысла никакого. Отлавливать кроссбраузерные моменты, исправлять ошибки, городить эффекты, виджеты и так далее - все то, что уже сделано другими - зачем???

Выбирайте из того, что уже есть и спите спокойно.
jQuery, Prototype, Mootools, ExtJS, YUI, dojo, Spry и так далее.
Для них, к тому же, сделана куча плагинов и расширений.
Говорится о 16 полезных решениях. Ни слова о своем фрэймворке. Тем более никто не заставляет сидеть и писать сови корявые заточки. Можно посмотреть как реализован анологичный функционал в опробованных решениях и перенести себе. А вообще все до кучи это сила...

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
...

int main()
{
std::cout
... порезали. Имелось в виду:
#include <iostream>
#include <time>
#include <math>
#include <iconv>
#include <string>
#include <stdio>
#include <iconv>
#include <regex>
#include <stdin>
#include <memory>
...

int main()
{
std::cout << "Мегасофтинко" << std::endl;
return 0;
}
или как то так =)
НЛО прилетело и опубликовало эту надпись здесь
getPosition ИЕ7 не работает (для ИЕ e.x просто и все)

Пример:
function findPosX(obj){
var curleft = 0;
if(obj.offsetParent)
while(1) {
curleft += obj.offsetLeft;
if(!obj.offsetParent)break;
obj = obj.offsetParent;
}
else if(obj.x) curleft += obj.x;
return curleft;
}

function isIE (){return navigator.userAgent.toLowerCase().indexOf("msie") > -1;}

function findPosY(obj){
var curTop= 0;
if(!isIE) curTop= obj.offsetHeight;
if(obj.offsetParent)
while(1){
curTop+= obj.offsetTop;
if(!obj.offsetParent) break;
obj= obj.offsetParent;
}
else if(obj.y) curTop+= obj.y;
return curTop;
}

function getPositionMy(e){
return {x:findPosX(e), y:findPosY(e)};
}
НЛО прилетело и опубликовало эту надпись здесь
А если у меня объект нулевой высоты, то функция getOffsetHeight вернет мне высоту кого-нибудь ненулевого предка, только не ноль.
В общем наличие очевидных недоработок заставляет с подозрением отнестись ко всем функциям.
В нашей компании разработан AJAX фреймворк, который включает множество таких и других полезных функций. Ему я по-крайней мере могу доверять, потому что он тестируется ежедневно в автоматическом режиме на всех основных браузерах. Так что любое изменение, ломающее функциональность или результаты, немедленно будет отслежено. Отлаживается и развивается в течении лет(!)
Поделиться исходниками даже утилит не могу. Сам фреймфорк можно скачать с http://bdn.backbase.com/
битая ссылка на "Source Code Highlighter."
Поправил, благодарю.
Кстати по поводу Number.prototype.NaN0. Было бы очень удобно собрать в одной библиотеке всенаиболее удобные раширения стандартных классов, таких как Object, Date, Number, String, Array и т.д. на практике сталкиваюсь с этой необходимостью очень часто.
как только вы расширите Object, на вас тут же набросятся 80% программистов, привыкших к for-in, и съедят заживо ; )
getOffsetHeight млин, столько ошибок


function findOffsetHeight(e) {
var res = 0;
while ((res == 0) && e.parentNode) {
e = e.parentNode;
res = e.offsetHeight;
}
return res;
}

function getOffsetHeight(e) {
return e.offsetHeight || e.style.pixelHeight || findOffsetHeight(e);
}
Две функции getTime() и getTimeDelta(timeBegin, timeEnd) вполне заменяются одной:

function $time(startTime)
{
var now = new Date().getTime();
return startTime ? now - startTime : now;
};


В ней нету timeEnd, но он и не нужен, если вместо получения timeEnd сразу замерять прошедшее время.
> или, по крайней мере, вызывайте их в фоне через setTimeout
В js нет "фона", есть один поток. Все, что вызвано через SetTimeout, затормозит броузер как обычно.
это из раздела "вредные советы"? ^_^
Не понял пункт:
Логгинг — иногда он нужен чтобы везде
Исправил. :)
а < li > всё равно осталась. Не закрытая. Не по стандартам живёте...
если вы "эмулируете" ООП в JS — вы просто не знаете этот язык и не умеете им пользоваться.
Напишите пожалуйста статью или дайте ссылку на то как правильно писать на javascript.
А то дофигища таких коментариев и ни одного примера.
>Напишите пожалуйста статью
Таких статей невероятно много в сети. Зачем повторяться?

>А то дофигища таких коментариев и ни одного примера.
Комментариев таких не видел. :) Примеры приводить не буду, лучше дам пищу для размышлений.

Зачем в JS функции первого класса и лексические замыкания? Зачем eval()? Зачем динамическая типизация? Зачем прототипы?
>Таких статей невероятно много в сети. Зачем повторяться?
Замечательно, но вот только я везде находил разной степени успешности попытки эмулировать обычные классы, наследование и тп.
Пример в студию, плз.

>Комментариев таких не видел. :) Примеры приводить не буду, лучше дам пищу для размышлений.
Да в каждом топике про javescript где упоминается попытка эмитировать классы в коментах обязательно появляется некто говорящий: "Это все фигня вы не шарите в тру javascript". Но никто не приводит примеров. Или это как неуловимый джо ;)

>Зачем в JS функции первого класса и лексические замыкания? Зачем eval()? Зачем динамическая типизация? Зачем прототипы?

И что это за пища для размышления ??? Перечислили фишки динамических и ф-циональных языков. (кроме прототипов естественно) Это знаем, пользуемся, все отлично, но где ООП ?
Меня интересует тру javascript парадигма проектирования и разработки через прототипное ООП, а не пустое умничанье терминами.

PS Интересно почему во флешевых ActionScript-ах используются обычные классы (хотя во всем остальном тот-же javascript), и python имеющий все что вы перечислили (кроме прототипов :) имеет вполне себе обычную нотацию классов? Просто потому что их разработчики не въехали в прототипную модель?
http://forum.dklab.ru/js/other/Prototype-basedNasledovaniyaVsEmulyatsiiClass-basedNasledovaniya.html
Спасибо за ссылку. Почитал. Опять все невнятно. Опять последователи тру прототипного ооп гнут свою линию - классы не нужны, при этом на предложение привести пример съежают с темы или пишут что у них мол на это нет времени ;)
Я понимаю что если думать в стиле классического ооп то непременно приходишь к недостаточности прототипного. Тут нужна другая психология, другие принципы, и мне интересно их понять. Книжки по javascript все о процедурном подходе и на примитивном уровне ооп. Статьи поверхностные. У гуру нет времени ;)
Не торопитесь с категоричными выводами.
Какую модель наследования использовать, решает каждый сам для себя (или команды) - это дело вкуса, того, кому что ближе, а не умения.

Интересно, по вашему, авторы большинства JS-фреймворков (а именно Mootools, Prototype, YUI, Dojo) тоже не знают язык и не умеют им пользоваться?
>Какую модель наследования использовать, решает каждый сам для себя (или команды) - это дело вкуса, того, кому что ближе, а не умения.
Согласен, что дело вкуса. Но "ближе-дальше" сильно меняется после того, как все-таки grok'нешь язык. :)

>Интересно, по вашему, авторы большинства JS-фреймворков (а именно Mootools, Prototype, YUI, Dojo) тоже не знают язык и не умеют им пользоваться?
Да. Забавный вывод, правда? :)
Впрочем, может быть, они просто ориентируются на "народные массы", которые с пеной у рта требуют "дайте нам тру-ООП!", потому что больше ничего не знают и не хотят узнать.

В общем, пойнт примерно такой: не пытайтесь писать в JS как в Java/C++/C#/Delphi, потому что не для того этот язык создавался. JS — это Лисп в синтаксисе Си, если угодно (бывалые Schemer'ы так его и воспринимают, кстати).
Чувствуете себя крутым, наверное, высокомерно называя лучших JavaScript-программистов мира неумелыми невеждами? Если вы настолько лучше их, может, продемонстрируете какой-нибудь значимый результат вашей работы с JavaScript?

"Народные массы" требуют классическую модель ООП не потому, что больше ничего не хотят знать, а всего навсего потому, что им так удобнее. В том числе и мне.

>потому что не для того этот язык создавался. JS — это Лисп в синтаксисе Си

Ну это крайне однобокий подход. JS - это язык, достаточно гибкий для того, чтобы в нём использовать в зависимости от задач и вкусов разные парадигмы. Пускай лисперы пишут на нём в стиле лиспа, поклонники классического ООП - соответственно, и т.д.

И не стоит тут раскидывать понты только потому, что вы прочитали пару статей Крокфорда или что-то в этом роде - мыслите шире. При всём уважении - терпеть не могу подобного.
>Чувствуете себя крутым, наверное, высокомерно называя лучших JavaScript-программистов мира неумелыми невеждами?
Я этого не говорил. А "лучшие программисты" тоже ошибаются, но "неумелыми невеждами" они от этого не становятся.

>Если вы настолько лучше их, может, продемонстрируете какой-нибудь значимый результат вашей работы с JavaScript?
О своем превосходстве над кем либо я не говорил. Невнимательно читаете? А насчет продемонстрировать результат — сейчас как раз пишу на JS, посмотрим, что из этого выйдет (может, действительно, что-то стоящее).

>"Народные массы" требуют классическую модель ООП не потому, что больше ничего не хотят знать, а всего навсего потому, что им так удобнее.
Здесь выбор примерно такой: либо узнавай новое и "более удобное" и пользуйся этим, либо пользуйся старым и проверенным, считая, что оно "удобнее".

>JS - это язык, достаточно гибкий для того, чтобы в нём использовать в зависимости от задач и вкусов разные парадигмы.
В этом топике продвигается только одна парадигма (как и практически везде в сети), против чего я и высказался.
Все ошибаются, но утверждать при этом, что эти программисты "не знают язык и не умеют им пользоваться" (как-будто вы знаете и умеете лучше их), очень глупо и некрасиво с вашей стороны.

>Здесь выбор примерно такой: либо узнавай новое и "более удобное" и пользуйся этим, либо пользуйся старым и проверенным, считая, что оно "удобнее".

Вы упустили из виду третий, самый существенный вариант: узнать достаточно о прототипичной модели наследования в JavaScript, оценить ее преимущества и недостатки перед классической моделью и сделать в конечном итоге осознанный выбор в пользу последней. Думаю, разработчики этих фреймворков поступили именно так.

>В этом топике продвигается только одна парадигма (как и практически везде в сети), против чего я и высказался.

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

>очень глупо и некрасиво с вашей стороны.
Станьте моей совестью? :)

Не пойму, почему вы так привязались к Симула-стайл ООП в JS. Под новым я имел в виду декларативное в целом и функциональное программирование в частности.

Сравните запросы к DOM с помощью CSS (или XPath) и с помощью методов DOM. Очевидно, что декларативный подход в этом случае короче, понятнее и легче поддерживается.

>Думаю, разработчики этих фреймворков поступили именно так.
Может, у них были (также) другие причины: сделать код понятнее обычному человеку (веб-дизайнеру, а не программисту), или ради своих же собственных maintainer'ов.
>Точную оценку знаний произвести невозможно, поэтому и сравнить тоже не получится.

Именно поэтому вам стоит забрать свои слова о знаниях и умениях любителей классического ООП обратно и извиниться за эту глупость.

>Не пойму, почему вы так привязались к Симула-стайл ООП в JS. Под новым я имел в виду декларативное в целом и функциональное программирование в частности.

Я не говорю, что это лучший подход во всех случаях. Я утверждаю, что каждый подход имеет право на жизнь и его выбор диктуется задачей, а не квалификацией программиста.

>Сравните запросы к DOM с помощью CSS (или XPath) и с помощью методов DOM. Очевидно, что декларативный подход в этом случае короче, понятнее и легче поддерживается.

Это частный случай. А вы попробуйте, скажем, написать JavaScript API для картографического сервиса типа Google Maps декларативным подходом.

>Может, у них были (также) другие причины

В любом случае они сделали осознанный и взвешенный выбор, который не делает их менее компетентными в вопросах JavaScript.
Добавлю и я несколько замечаний :)

вместо document.documentElement ? document.documentElement : document.body
можно написать просто document.documentElement || document.body

строку (e.currentStyle ? (parseInt(e.currentStyle.borderLeftWidth)).NaN0() : 0)
можно сократить parseInt(e.currentStyle && e.currentStyle.borderLeftWidth).NaN0()
хотя выходит что вы не учитываете padding. Вместо этой злой конструкции достаточно использовать e.clientLeft. К сожалению до 3-й версии в FF не было поддержки clientLeft. Однако есть более простой способ для тех версий использовать малодокументированый метод document.getBoxObjectFor. У IE есть так же более простой способ извлечения координат метод element.getBoundingClientRect. Этот метод приняли в стандарт, и FF3 и Opera9.5 его поддерживают. Так что перебор всех offsetParent'ов должен быть последним вариантом.

Строка
if (aligned == null) aligned = false;
не нужна, так как aligned ? .. : ..; отработает одинакого и при aligned == null и при aligned == false

walkTree & searchTree крайне неоптимизированы (особено по части использования node.childNodes.length). Возможно Вы удивитесь, но эти функции можно написать без рекурсии и использования childNodes - будет значительно быстрее работать.

node.nodeName !== '#text' & node.nodeName !== '#comment'
тут совсем не ужен оператор !== достаточно != (не равно). Но в любом случае кто вас научил проверять тип элемента? Для этих целей есть свойство nodeType, вот его и нужно проверять (nodeType != 3 && nodeType != 8). Хотя стоило бы конечно смотреть есть ли свойство attributes у node (у комментариев и текстовых узлов его нет).

Не сообразил зачем вы рекурсивно удаляете (отвязываете) все дочерние узлы ото всех в removeChildrenRecursively. Имхо достаточно удалить только дочернии. Оптимальным будет вариант:

while (node.lastChild)
node.removeChild(node.lastChild);

В случае с консолью, чем Вас не устроил вариант

if (typeof console != 'undefined')
console = {
log: function() { },
info: function() { },
warn: function() { },
error: function() { }
};

Зачем создавать класс и сущность от него?
НЛО прилетело и опубликовало эту надпись здесь
// +60 баллов? Я в шоке. Я бы оштрафовал программера, которые начинает изобретать велосипед, причём далеко не самую удачную модель. Сейчас объясню почему.

omg = {lol: {wut: 0}};
cloneObj(omg).lol.wut = 1;
alert(omg.lol.wut); // 1, omg lolwut?

Человек, которому поручат поддерживать такой код, очень обрадуется что ему кроме Prototype и jQuery теперь нужно постигать чьи-то недокументированные творения, которые чудесным образом перестанут работать со следующей версией IE.

Мой список полезных функций, которых почему-то нет во фреймворках:
isEmpty - возвращает true не только для undefined, false и 0, но также для [] и {}.
escapeHtml - преобразование html в entities, удивительно, но в явном виде есть не во всех фреймворках
toArray - преобразование объектов в массивы, полезно когда нужно сделать .pop() или узнать количество деток
date - форматирование дат, аналог функции date из PHP
Ситуации бывают разные, специфика работы разная. Я, к примеру, занимаясь поддержкой и разработкой самых разных проектов для разных клиентов не раз сталкивался с проблемами вызванными использованием готовых javascript фреймворков. В частности очень долго и активно использовал библиотеку prototype.

Несколько пунктов в защиту своих библиотек.

1. Грузить под сотню кил библиотеки когда используешь только $() и манипуляции с DOM напрягает.
2. Не раз приходилось переписывать некоторые ф-ции библиотеки на свои менее универсальные но более быстрые.
3. Использование фреймворков для написания реюзабельных компонентов зло(ну или по крайней мере очень спорно, нужно хорошо взвесить все за и против). Примеры... Надо было вставить на страницу активно использующую prototype два готовых чужих компонента, достаточно сложных чтобы обломаться их писать самостоятельно. Но вот не задачка... На странице prototype 1.5.1.1, один компонент использует 1.5.1, а другой 1.6. И при этом все так удачно написано что не совместимо с двумя другими версиями библиотек.
В тоже время не раз радовался тому что написал свою фичу на pure javascript и теперь без проблем могу ее вставить в проект с jQuery или со старой версией prototype.

Если я не прав и есть какое-то идеальное решение, позволяющее не плодить свои библиотеки, то буду очень рад и благодарен ;) так как самого достала эта проблема.
Кстати мне вот еще интересно почему вы делаете так
someString in oc(['foo', 'bar', 'etc'])
Когда достаточно
['foo', 'bar', 'etc'].indexOf(someString) != -1
полагаю это быстрее на порядок. В старых версиях IE (до 5.5) нет метода indexOf, но там так же нет и someString in object.
Это не ко мне вопрос ;) Я так не делаю.
шестой тоже не поддерживает. впрочем, лучше написать для него этот метод через перебор...
1. Правильно упакованный jQuery + gzip выливается в 12 кило на клиенте. Mootools и того меньше. Если же каждый плагин реализует кроссбраузерную работу с событиями, DOM, Ajax, то в сумме они могут весить гораздо больше, чем библиотека, в которой подобного дублирования кода нет.
2. Оптимизированные версии стандартных функций я добавляю как плагины во фреймворк, всё таки выигрыш по скорости в 5 раз - это не шутки.
3. Уровень кода в сторонних поделках очень низкий. Обычно я готов к тому, что придётся исправить 5-10 багов. Этот чёрт не так страшен, как его малюют.

Оптимальное решение для проекта любой сложности - использовать популярные библиотеки.
У них есть документация, они хорошо оптимизированы, протестированы. Новые люди знают как ими пользоваться. С выходом новой версии браузера добрые дяди без нас решают проблему совместимости.
1. Zip это отлично, но что делать со временем которое тратит браузер на то чтобы распарсить и выполнить весь этот javascript ?

2. Посмею предположить, что вы используете оба фреймворка jQuery и Mootools. Как вы решаете проблемы, типа, написал компонент под jQuery, а теперь он нужен в проекте с Mootools?
Переписываете и поддерживаете две версии компонента или добавляете jQuery в проект?

3. Баги то бываю такие которые проявляются не сразу или достаточно не очевидно.

4. Кроме всего прочего добрые дяди убивают совместимость со старыми версиями фреймворков ;)

Почему крупные компоненты, типа TinyMCE не используют фреймворков ? На сколько меньше стало бы пользователей того же TinyMCE если бы они привязались, к примеру, к jQuery ?

Возможно мои выводы связаны с негативным опытом использования фреймворка prototype. Давно собираюсь попробовать jQuery и Base2.
Можно, воспользовавшись концентрацией javascript-спецов в этом посте, спросить, чем этот скрипт, выдающий flash-баннеры, может раздражать Оперу?
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
>>3. Нижеприведенная функция клонирует любой объект вместе со всеми его свойствами

она не сделает того, что от неё ожидается в некоторых случаях:

var a = {};
a.a = "hello";
a.b = new Array("world", "!");
// (1)
alert(a.b[0]);

var b = cloneObj(a);
a.b[0] = "n";

// (2)
alert(b.b[0]);

результат:

(1) world
(2) n
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.