javascript
Одно из различий Python и JavaScript
Чем дальше, тем между большим количеством языков программирования мне приходится переключаться. Одно из различий объектной модели Пайтона и ДжаваСкрипта мне портит кровь (у них парадигмы ООП вообще сильно различаются), если я вовремя не соображу, что надо переключиться с одного языка на другой.
Суть в том, что в Пайтоне метод ходит в гости со своим контекстом:
class A:
test = 'A'
def show(self): print self.test
class B: test = 'B'
a, b = A(), B()
show = a.show
b.show = a.show
show() # A
b.show() # AТогда как в JavaScript такой код будет работать совершенно иначе, там методы в чужой монастырь со своим уставом не ходят (если их не попросить):
var test = 'global';
A = function () {
this.test = 'A',
this.show = function () { alert(this.test) }
};
B = function () { this.test = 'B'; }
a = new A(); b = new B();
b.show = a.show
show = a.show
show() // global
b.show() // B
b.show.apply(a) // AПоявление «global» наверное надо разъяснить тем, кто JS знает плохо. На самом деле первая строчка (в данном случае) может читаться как «window.test = ’global’», а «show = a.show» как «window.show = a.show», тогда, должно быть, всё
Минус ноль в JavaScript
Я, конечно, знаю, что JavaScript хранит числа по стандарту IEEE 754, но всё больше
Но вот о существовании минус нуля я
Но, оказывается, в редких случаях отрицательный ноль может себя проявлять иначе, чем ноль положительный.
Как вы можете получить минус ноль? Например, просто написав
Похоже, что в реальном коде минус ноль может проявить себя в двух вещах: делении и операции atan2, именно так его и можно отличить от положительного нуля:
function isNegativeZero(x) {
return x === 0 && (1 / x) === -Infinity
}
function isNegativeZeroToo(x) {
return x === 0 && Math.atan2(x, x) < 0
}JavaScript: небезопасная изоляция скриптов
Я смотрю многие начинают задумываться об изоляции JavaScript, подключаемых в контекст страницы. Например, вы подключаете
Сейчас считается, что безопасным методом является
(function (window, alert) {
alert('Функция «alert» изолирована и доступ к методу из «window» теперь получить нельзя');
})({}, function (){})Это не правильно.
Такой вызов вас ни от чего не защищает, более того, можно запросто «восстановить справедливость» и получить изнутри такого скрипта доступ к оригинальному window:
<script>
(function(window, alert){
alert('Пичалька');
(function(){ with(this) {
alert('Уже всё хорошо');
}}).call(null);
})({}, function(){})
</script>В общем случае идея такой изоляции — плохая. Я не видел ни одного удачного примера подобной изоляции и не смог придумать его самостоятельно.
Небольшая задача на Пайтоне
Вот вам небольшая задача на Пайтоне, для того, чтобы понять как у вас с функциональным программированием. Выполнить надо в уме (я смог, значит это возможно). Что вернёт следующее выражение:
(lambda x:x(x))(lambda z: lambda y:z)(1)(2)(3)Добавлено позднее: если
(function (x) x(x))(function (z) function (y) z)(1)(2)(3)Невероятный JavaScript
Насколько запутанный JavaScript вы можете написать? Хотя
В блоге Shadowflux образчик хорошо запутанного кода с объяснением работы:
($=[$=[]][(__=!$+$)[_=-~-~-~$]+({}+$)[_/_]+
($$=($_=!''+$)[_/_]+$_[+$])])()[__[_/_]+__
[_+~$]+$_[_]+$$](_/_)Выглядит довольно страшно, но, если разобраться, ничего сложного. Напоминает старый добрый Perl.
Конструкцию «with» убрали в strict mode в ECMAScript 5?
with(){} statements are dead when strict mode is enabled — in fact it even appears as a syntax error. While the feature was certainly
mis-understood and possiblymis-used I’m not convinced that it’s enough to be stricken from the record.
Я, конечно, понимаю чем плоха конструкция with, но отключать её в strict mode… Мне кажется излишним.
ECMAScript 5, кстати, будет в FireFox 4.
Сериал для программистов на JavaScript
Не пропустите новогодний сериал для программистов — мы с неким LO сокращаем мой второй вариант игры «Tank 1K», написанный по рождественским правилам конкурса JS1K (программ на JavaScript, умещающихся в 1КБ).
Уже сократили с 1023 до 773 770 759 752 723 байта (более чем на 29% и это на таком крошечном размере).
Для меня — полезное соревнование, тренинг, о котором только можно мечтать, у LO отлично варит голова. Для вас — возможность посмотреть как в JS можно сократить размер программы. Уже сейчас видно, что из некоторых ходов вполне можно вывести правила, например: «если у тебя в программе есть пустые скобки любого вида, посмотри нельзя ли их
Если
localStorage для Internet Explorer 6 и 7
Написал небольшой класс в JavaScript для поддержки API localStorage в IE 6 и 7. localStorage — это браузерное хранилище
Доступ к значениям как к свойствам класса не реализован. Прежде всего потому, что в JS в этих версиях IE нет сеттеров и геттеров, а для того, чтобы воспользоваться onpropertychange мой объект надо поместить в DOM, что порождает массу гемороя, типа присутствия свойств из DOM, а не из хранилища.
Так же я не сделал события onstorage и onstoragecommit, потому что не придумал для чего это нужно (а второе корректно реализовать вообще нельзя).
Ещё не реализовал нестандартное, но полезное расширение remainingSpace, потому что в общем случае нельзя сказать сколько места ещё осталось в userData, так как квота зависит от зоны сайта (доверенная, интранет и так далее).
С большой вероятностью эта зона, конечно же, «интернет» (то есть квота 1МБ), но квоты localStorage сильно отличаются по механизму от userData, у последнего две квоты — на документ (в зоне «интернет» это 128КБ) и на домен (упомянутый мегабайт). Вполне может случится, что квота «на документ» ещё не исчерпана, а доменная уже да.
Зато я реализовал exception, который бросается в том случае, если IE говорит, что квота исчерпана.
В общем, основные вещи есть. Пример использования:
// .-~*´¨¯¨`*·~-.¸ тут подключаем библиотеку ,.-~*´¨¯¨`*·~-.¸
// записываем два значения
try {
localStorage.setItem('key1', 'myvalue1');
localStorage.setItem('key2', 'myvalue2');
} catch (e) {
if (e.description == 'QUOTA_EXCEEDED_ERR') {
alert('Нет места');
} else {
alert('Что-то не так, не знаю что.');
}
}
// смотрим значение по ключу «key1»
alert(localStorage.getItem('key1'));
// смотрим первое значение (по номеру), нумерация с нуля
alert(localStorage.key(0));
// удаляем значение по ключу «key1»
alert(localStorage.removeItem('key1'));
// смотрим сколько ключей осталось
alert(localStorage.length);
// очищаем хранилище полностью
alert(localStorage.clear());Порисовал немного на теге CANVAS, ничего интересного

Попробовал порисовать на теге CANVAS, хотелось хоть
<canvas width="500" height="240"></canvas>
<script type="text/javascript">
(function (c) {
var img = c.createImageData(500, 240);
var putPixel = function (x, y, c) {
var index = (x + y * 500) << 2;
for (var i = 0; i<4; i++) {
img.data[index+i] = c[i];
}
};
var x = 0, y = 0, color, leaf, idx,
k = [
[ 0.00, 0.00, 0.00, 0.16, 0.00, 0.00 ],
[ 0.85, 0.04,-0.04, 0.85, 0.00, 1.60 ],
[ 0.05,-0.26, 0.23, 0.22, 0.00, 1.60 ],
[-0.15, 0.30, 0.26, 0.24, 0.00, 0.44 ],
];
for (var i = 0; i<200000; i++) {
leaf = Math.random();
if (leaf <= 0.010) leaf = 0; else
if (leaf <= 0.860) leaf = 1; else
if (leaf <= 0.930) leaf = 2; else
leaf = 3;
x = x * k[leaf][0] + y * k[leaf][1] + k[leaf][4];
y = y * k[leaf][2] + y * k[leaf][3] + k[leaf][5];
putPixel(parseInt(y * 55), 120 - parseInt(x * 40), [10, 100, 20, 255]);
}
c.putImageData(img, 0, 0);
})(document.getElementsByTagName('canvas')[0].getContext('2d'));
</script>Даже создатели Dojo не читают документацию
Class Sample
Public Property Let someprop(val)
…
End Property
Public Property Set someprop(val)
…
End Property
Public Property Get someprop
…
End Property
End ClassДва вида сеттеров связаны с тем, что в VBScript довольно чётко различаются передача по ссылке и по значению (например, можно в параметрах функции указать «ByRef» или «ByVal»), кроме того, у сеттеров и геттеров есть ещё один параметр, благодаря чему можно перехватывать вызов методов и делать совсем уж странные, с точки зрения JavaScript, штуки.
Впрочем, к чёрту подробности.
Один из разработчиков
Но в IE уже есть специальный метод объекта window, который занимается тем же — execScript, вторым параметром надо задать «vbscript» и voilà!, мы вызываем VBScript из JavaScript.
Я этот метод
Ограничения на localStorage
localStorage —
Last time I’ve checked, Chrome 5.0.375.99 beta let me save
2600-2700 thousands of characters, Firefox 3.5.9 —5200-5300k, Explorer 8 —4900-5000k, and Opera 10.60 popped a dialog, letting me give the script unlimited storage.
Причём, я ещё заметил, что браузеры с разной скоростью выделяют место под хранилище. Некоторые («Опера», например, выделяет его за время O(1)), другие заметно замедляются с ростом размера выделяемой памяти.
Добавлено позднее: кстати. У объекта localStorage есть несколько методов, в тот же самый объект отображаются, как свойства, пары ключ/значение. В любом браузере, кроме FF, можно запросто перезаписать любой из методов этого объекта. Только FF предусмотрительно не позволяет этого делать. Жаль только, что он не позволяет этого делать молча, не выбрасывая exception.
Если читать стандарт, то ощущение такое, что авторы просто не учли этого случая и разрешают перезаписывать эти методы.
JS — слишком сложный язык для большинства
JS — честное слово, это
Есть такой прекрасный сайт — «WTFJS», прекрасен он тем, что отлично иллюстрирует эту мысль. Встречаются там, конечно, совершенно идиотские примеры поведения интерпретаторов, но большая часть — совершенно нормальные вещи, в которое люди восторженно тыкают пальцем, потому что изучали JS «на примерах».
Скажем, вот, пример с сайта:
var void = function () {}
//=> SyntaxError: missing variable nameЯ
with в JavaScript и VBScript
Одной из бесполезных конструкций языка JavaScript называют «with». Неспроста, эта конструкция непрозрачна и потенциально может создать непростые проблемы. Небольшой код:
with (MyObject) {
width = '100px';
height = '200px';
display = 'block';
}Что будет, если свойства с таким именем не найдётся? Код заменит значения переменных width/height/display или же создаст их, если их ещё не было. Что приведёт к проблемам, если мы в связанном коде
С языком VBScript я знаком с тех пор как программировал, используя технологию ASP. В дальнейшем, я иногда использовал его, чтобы программировать
Этот язык я,
With MyObject
.width = "100px"
.height = "200px"
.display = "block"
End WithЗаметили точки впереди? Они говорят о том, что используются не просто переменные, а свойства (ну или методы) объекта, указанного в «With». Вот так просто решается куча проблем.
Wolf 5k strikes back
Забавная была игрушка «Wolf5K». Это игра на JavaScript, занимающая пять килобайт (!). Был такой конкурс
Ребята произвели фурор тогда, они уместили в этот размер небольшую псевдотрёхмерную бродилку. Никаких CANVAS! Хитрость в том, что вся графика (кроме кровищи) делается в формате XBM и передаётся тегу IMG через схему «javascript». Игрушка работала в IE5, IE6, Mozilla 1.1+ и Netscape 4.77 для Мака.
Формат XBM — это текстовый формат
В общем, захотелось мне
javascript:void(eval(X.toString().replace(/"j.*?;"/, '"data:image/x-xbitmap," + encodeURI(im)')))В IE
Добавлено утром: читатели сообщают, что в «Сафари» тоже работает.
Короткий способ определения IE через JavaScript в IE9 не сработает
Из блога IEBlog:
var len = [1,2,3,].length;
alert(len); //should be 3, IE8 says 4В IE9 поправили застарелый баг — Internet Explorer добавляет ещё один элемент в массив, если в конце перечисления элементов массива есть запятая. На этом основан самый короткий способ проверки на IE через JavaScript. По стандарту последняя запятая игнорируется. IE9 теперь следует стандарту.
Не будет работать и проверка через «\v» (цитата из того же блога):
alert("\v"==="v");//IE8 said true, should be false
alert("\v"==="\u000b");
//IE8 said false, should be trueВ общем, полагаться на хаки в таких проверках будет нельзя. Думаю, единственный надёжным способом будет условная компиляция:
if (/*@cc_on!@*/0) {
// IE
}P.S. А вот найденную мной… особенность метода split в IE9 так и не поправили.
Обнаружение версии IE в режиме эмуляции через условную компиляцию JavaScript
В свежей статье в блоге IE есть ответ на вопрос как обнаружить версию браузера Internet Explorer в любом режиме (например, в режиме эмуляции другой версии):
@_jscript_version statement is actually an indicator of which version of JScript is in use by the browser as a whole. In ALL document modes of IE9, this statement currently equates to “9”. In ALL document modes of IE8 it equates to “5.8” and in IE7 it is “5.7”
Отсюда вывод:
/*@cc_on
@if( @_jscript_version == 5.8 )
// Это полюбому IE 8
...
@end
@*/То есть (перевожу) «@_jscript_version» в IE8 всегда равно «5.8», в IE7 — «5.7» , а в IE9 — «9».
Тег video и IE
Интересно, когда консорциум W3 отвернулся от тега OBJECT? Помнится, даже IFRAME старательно пытались заменить на OBJECT, а сейчас
Тем не менее, API ActiveX Windows Media Player хорошо документирован и работать с ним очень просто. Я в последнее время мало программирую на JavaScript и вчера вечером, чтобы освежить знания, попробовал сделал плеер, похожий на VideoJS, но только для IE — с тегом OBJECT и применением VML.

Сегодня утром решил не останавливатся на достигнутом и за завтраком начал делать другую
P.S. Некоторые вещи там сделаны неоптимально, так что я бы очень рекомендовал несколько подчистить код, если
P.P.S. Кнопочки и progress bar нарисованы через VML.
Perl write-only vs. JS write-only
Perl, говорите? Хехе. Этот небольшой JavaScript выполняет alert(1):
(É=[Å=[],µ=!Å+Å][µ[È=-~-~++Å]+({}+Å) [Ç=!!Å+µ,ª=Ç[Å]+Ç[+!Å],Å]+ª])() [µ[Å]+µ[Å+Å]+Ç[È]+ª](Å)Можете попробовать в браузере.
Автор — Йосуке Хасегава Э. Вела.
JavaScript V8 и nginx
Игорь Сысоев написал интересную статью «Почему Google V8 пока не подходит для встраивания в сервера», краткая выжимка:
Поскольку V8 разрабатывается в первую очередь для Chrome, то это наложило на него существенный отпечаток и, перефразируя высказывание Генри Форда о цвете машины, можно сказать, что V8 будет хорошо работать в любой программе, при условии, что эта программа называется Chrome. (…) Подытоживая вышеописанное, можно сказать, что на данный момент (версия 2.0.6.4, февраль 2010 года) V8 не подходит для серьёзного встраивания в сервера.
JavaScript: это IE?
Aleko придумал новый (более короткий, чем известный до этого)
if(-[1,]) {
// код для нормальных браузеров
} else {
// код для IE
}Подробный принцип действия хорошо описан в блоге у Aleko. Основан хак на старом баге JavaScript в IE, который Microsoft пока не исправила (и неизвестно будет ли исправлять), но с IE9, я считаю, надо быть осторожными — там грядут очень уж глобальные изменения, хак может и не работать.