В прошлой статейке я обещал свести все десять экранов флуда в таблички.
Вот, пожалуйста: сводные таблички.
В прошлой статейке я обещал свести все десять экранов флуда в таблички.
Вот, пожалуйста: сводные таблички.
Статья написана по мотивам бессмысленной и беспощадной дискуссии на javascript.ru.
Итак, есть у нас программа на языке JavaScript, в ней есть какие-то значения, а у значений есть какой-то тип. И вот вопрос: как нам узнать, этот самый тип значения?
И второй вопрос: а действительно ли нам надо его узнавать и нельзя ли обойтись другими средствами?
Под «типом» я здесь подразумеваю более широкое понятие, чем встроенный тип, возвращаемый оператором typeof
. Это, например, «массив» или «элемент DOM», которые для typeof
все на одно лицо ("object"
). Вернее их было бы назвать «классами типа object», но не будем пока погружаться в терминологию.
В большинстве случаев выяснять тип не требуется.
Если функция принимает в качестве аргумента HTMLDivElement с которым выполняет какие-то манипуляции и в документации к ней указана, что она принимает HTMLDivElement, то она может рассчитывать на то, что получит именно HTMLDivElement.
А если программист вызывает её со строкой в качестве аргумента, то это проблемы программиста. И проблемы в том самом месте, где он её вызывает.
При попытке же написать более универсальную функцию, знание типа (класса) переменных бывает не лишним.
Например, хотим мы создать функцию вроде map()
, которая перебирает элементы структуры, выполняет над ними какие-либо действия и возвращает аналогичную структуру, где вместо исходных элементов результаты этих действий. Или merge()
— рекурсивное слияние двух структур.
Здесь уже перебирать и сливать различные значения нужно по разному. Простые объекты через for (k in obj)
, массивы и подобные им (arguments
, HTMLCollection
) через for (i=0;i<len;i++)
. При этом Function
, например, тоже объект со своими свойствами, но при слиянии мы вправе ожидать, что скопируется сам объект функции, а не будут рекурсивно сливаться его свойства.
Для этого нам нужно знать, что перед нами — сугубо говоря, «словарь», «список» или «индивидуальный объект».
Остальной текст под катом
Лет 15 назад какой-то кудесник написал следующую функцию на тогда ещё новом языке JavaScript:
function getCookie(name) { var start = document.cookie.indexOf(name + "="); var len = start + name.length + 1; if ((!start) && (name != document.cookie.substring(0, name.length))) { return null; } if (start == -1) return null; var end = document.cookie.indexOf(';', len); if (end == -1) end = document.cookie.length; return unescape(document.cookie.substring(len, end )); } |
С тех пор она обошла весь интернет и сотню рейтингов типа «10 самых обосраться лучших JavaScript-функций за все времена».
С тех пор все подряд либо тянут её себе, либо, как обычно, переписывают на свою «ещё более лучшую, ведь я программист», но везде впихивают этот грёбаный indexOf()
.
Чем он вам понравился?
Даже Дэвид Флэнаган в своём «подробном руководстве» не удержался.
indexOf(name + "=")
— мы здесь не переменную «name» ищем, мы ищем переменную, заканчивающуюся на «name».
Что следующий код нам вернёт?
setCookie("sex", "yes"); setCookie("x", "no"); console.log(getCookie("x")); |
Правильно:
sex=yes; x=no;
Ну и escape/unescape
совершенно для других целей нужны.
А посему:
function getAllCookie() { var parts = document.cookie.split(";"), cookie = {}, part, name, value, i, len = parts.length; for (i = 0; i < len; i += 1) { part = parts[i].split("="); name = part[0].replace(/^\s+/, "").replace(/\s+$/, ""); value = (part[1] || "").replace(/^\s+/, "").replace(/\s+$/, ""); cookie[name] = decodeURIComponent(value); } return cookie; } |
Можно много говорить по поводу того, нужны ли в JS навороченные фреймворки, а если нужны, то что из них говно, а что нет. Но по работе мне сейчас приходится использовать prototype.js, поэтому буду писать про него. Тем более, что не такое это и говно, если правильно готовить.
От нефег делать сделал решалку судоку.
На данный момент немного глючит под Firefox и совершенно не работает под всем остальным.
Для примера нажмите справа ссылку «вариант раз», а затем кнопку «запустить считалку».
Умность считалки будет повышена (а кроссбраузерность добавлена) в следующий нефег делать.
Детские ошибки, которые в последнее время отъели у меня немало времени и нервов. Разрабатывая сложные вещи не забывайте и о подобной чепухе. (Все примеры сведены к бессмысленному минимально иллюстрирующему коду).
В PHP, как самом умном, результатом операторов && и || является TRUE/FALSE. Казалось бы, логично, что результатом логического оператора является логическое значение. Однако, другие языки развратили меня тем, что возвращают в этом случае значение одного из аргументом.
В итоге строка $x || $y || $z
вместо целочисленного значения одной из переменных, вернула предательский TRUE. После нелёгких поисков пришлось одну строку заменять на кучу ветвлений.
Сделать такой вот список. Несколько скрытых пунктов. Жмём на заголовок — текст раскрывается, жмём ещё раз — закрывается.
Усложняем задачу:
1. Тексты должны не просто открываться, а плавно раскрываться.
2. Если нажать на заголовок в том момент, когда блок раскрывается, он должен начать с той же позиции закрываться.
3. Еще быстро нащёлкать несколько заголовков, блоки должны открываться/закрываться параллельно, не мешая друг другу и уж тем более работе с другими элементами.
Статья с dev.opera.com, достаточно старая (ноябрь 2006), но для начала вполне подходящая.
Оригинал: | http://dev.opera.com/articles/view/efficient-javascript/ |
Автор: | Mark ‘Tarquin’ Wilton-Jones |
Перевод: | Григорьев Олег |
Тип перевода: | Весьма вольный |
Лицензия: | Creative Commons Attribution, Non Commercial — Share Alike 2.5 license |