Нестандартное поведение стандартного оператора ||
Иногда при кросс браузерном программировании бывает нужно выбрать из двух или более переменных которые зависят от типа браузера. Например типичный пример - отслеживание событий мыши - в IE параметры события берутся из глобального объекта event а в Firefox и многих других браузерах event передается как формальный параметр в обработчик события. Поэтому необходимо выбирать тот или иной способ получения этого объекта в зависимости от того какой браузер.
Самое первое, что приходит на ум это использовать тернарный оператор "<condition>?<if true>:<if false>":
a.onclick = function(e){ var ev = e?e:event; //далее работаем с ev }
Сегодня мне предложили еще более короткую запись:
a.onclick = function(e){ var ev = e||event; //далее как обычно }
Все отлично, все логично, но почему это работает? В MSDN четко сказано что || оператор логический и возвращает он true или false в зависимости от входных параметров. Если параметры на входе не логические то приводятся к логическим, т.е. не должно так работать а работает.
Скорее всего операция || возвращает первый не ложный аргумент, причем возвращает по ссылке в чем нетрудно убедиться:
var v1; //undefined var v2 = {}; var result = v1 || v2; alert(result===v2); //true
Интересно, такое поведение где нибудь документировано или это хак?
UPD: Оказыватся у Мозиллы все подробно на этот счет расписано:
https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Operators/Logical_Operators
Базовый класс для наследования в JavaScript
Под впечатлением класса разработанного Дином Эдвардсом создал свой собственный класс, который позволяет значительно упростить структуру программ на JavaScript где необходимо неследование.
Основные особенности следующие:
- маленький и простой - неминифицированный размер: 622 байта.
- конструктор описывается явно как функция с именем 'constructor'
- наследование статических и обычных членов класса
- при определениии объекта не используется MyClass.prototype;
- не используются глобальные функции для создания цепочек прототипов;
- не изменяется Object.prototype.
Вот пример использования:
var Animal = BaseClass.extend({ constructor:function(){ alert("Anumal is created!"); }, say:function(){ alert("hm..."); } }); ver Cow = Animal.extend({ constructor:function(){ alert("Cow is created!"); }, say:function(){ alert("mooo"); } }); var cow1 = new Cow(); cow1.say();
Фактически, от версии Дина отличается только отсутствием статических методов на этапе наследования - их можно и явно прикрутить, что улучшит читаемость кода, также отсутствует метод super, на мой взгляд у Дина эта штука будет понижать производительность, перегруженных функций независимо используется super или нет, поэтому я решил от неё отказаться, к тому же её можно эмулировать просто отдельной функцией.
Upd. Позже я пересмотрел мысль насчет super и включил её в реализацию метода. В ztools.org можно найти последнюю версию функции.
!! в JavaScript
Разглядывая чужие исходники постоянно натыкаюсь на использование конструкций вида !!(document.evaluate). Догадывался что это проверка переменной на существование, и вот теперь убедился с этом лично.
Если выполнить указанный код в мозилле покажет true если в Explorer - покажет false, что и требовалось доказать т.к. Explorer не поддерживатет XPath.
Конечно, гораздо логичнее было сделать проверку с использованием if, но поскольку в JavaScript размер кода является решающем фактором то разработчики намеренно идут на всякого рода ухищрения чтобы сократить запись иногда даже в угоду удобочитаемости.
JavaScript наследование
Разбирая исходники библиотеки mootolls обнаружил ссылку на блог некоего Дина Эдвардса (Dean Edwards). Дин предлагает свою версию эмуляции объектно-ориентированного программирования на JavaScript.
Основные особенности следующие: не нужно кажный раз для расширения класса писать MyClass.prototype; можно обращаться к методам базового класса из переопределенных методов (аналог super в Java); поддержка статических методов свойств; не используются глобальные функции для создания цепочек прототипов; не изменяется Object.prototype.
Вобщем довольно интересная штука, хотя на мой взгляд super в общем то не очень и нужен, хотя идея сама по себе, на мой взгляд, классная и реализация отличная.