93 заметки с тегом

javascript

Что есть истина?

У нашего бывшего сотрудника в фейсбуке увидел ссылку на любопытную задачку — может ли (a == 1 && a == 2 && a == 3) быть «истиной» в ДжаваСкрипте?

Не заглядывая в статью, я предложил два варианта, вполне очевидный первый:

a = ((counter) => ({valueOf:() => ++counter}))(0)
// {valueOf: ƒ}
a == 1 && a == 2 && a == 3
// true

И второй — на суррогатных парах. Но по ссылке есть ряд других занимательных способов — через геттеры, похожие символы Юникода (мне приходил в голову такой вариант, но я не смог подобрать трёх символов, одинаковых на вид), другие специальные методы и прочее. Больше всех мне понравился такой способ:

a = [1,2,3];
a.join = a.shift;

a == 1 && a == 2 && a == 3
// true

Очень просто и элегантно — массив при преобразовании в скаляр в ДжаваСкрипте, всегда сначала преобразуется в строку значених, объединённых через запятую. В коде выше метод для объединения заменяется методом, который забирает из массива первый элемент. И всё работает как требуется — при каждом сравнении массива с числом, забирается первый элемент массива.

24 января   javascript   программирование

Что-то не вижу — быть или не быть?

Программа, выводящая монолог Гамлета (19.86КиБ)
Так выглядит программа, выводящая монолог Гамлета

Слово «выглядит» в подписи ко скриншоту выше упомянуто неслучайно — программа написана так, что видимое — только надводная часть айсберга.

Уже в те далёкие времена, когда я только ещё начинал писать на ДжаваСкрипте, программисты на форумах задавались вопросом можно ли как-то защитить свои программы на этом языке от обратной разработки. Помню «Микрософта» в своём браузере позволяла шифровать исходный код, но эту «защиту» довольно быстро поломали, очень уж она была простая.

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

С тех пор эти инструменты застыли примерно в том же состоянии, но теперь, мне кажется, в этом деле наметился прорыв.

Некто ФейкЮникод, разместил скрытое послание внутри суррогатных пар Юникода. Я когда-то делал что-то похожее на пробелах нулевой длины, но моим способом сильно не разбежишься — алфавит маленький.

Что такое суррогатные пары расписывать не буду, статей на эту тему предостаточно, главное, что их не видно и они могу быть частью (кроме первого символа) любого идентификатора ДжаваСкрипта.

Я попробовал использовать способ с суррогатными парами, чтобы скрыть монолог Гамлета внутри программы на ДжеЭсФаке (способ написания программ на ДжаваСкрипте, когда не используются алфавитно-цифровые знаки), плюс этими же парами закодировал имена переменных.

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

2017   javascript   программирование

F★ckJS на поло

Поло со значками (110.09КиБ)
Поло с программой на ДжаваСкрипте, написанной четыре года назад

Очень в тему к предыдущему посту на работе нашёлся мешок с поло размера XXL (из-за размера и сохранился, остальные разобрали).

На поло программа на ДжаваСкрипте, которую я писал к какому-то событию, должно быть готовились к какой-то конфереции — если её запустить в консоли браузера, появляется надпись «prihodite rabotat 88002005221». У меня в «исходящих» сохранилось письмо от 11 марта 2013 года, где я высылаю оригинал этой программы нашему дизайнеру, четыре года уже прошло, надо же.

2017   javascript   программирование

«Странный» JS

В ДжаваСкрипте полно странностей, да, но популярная картинка, которая получила сейчас широкое хождение (не буду её приводить, просто суть перепишу) имеет отношение только к безграмотности её авторов. Суть такова:

[] + [] // массив + массив
"" // результат — пустая строка

[] + {} // массив + объект
"[object Object]" // В результате получаем объект? Ну ок

{} + [] // объект + массив
0 // 0? Реально?

{} + {} // объект + объект
NaN // Not a Number? WAT?

Выглядит очень всё ооочень странно, если думать, что происходит именно то, что написано в коментариях справа. На самом деле происходящее неверно интерпретировано авторами.

В ДжаваСкрипте фигурные скобки, помимо объекта, задают ещё и блок кода. В данном случае все «объекты» слева — на самом деле блоки кода. Откроем консоль и попробуем это доказать:

Вот что происходит на самом деле (9.90КиБ)

Как видите, в левый блок можно без труда добавить код и станет очевидно, что это не описание объекта. Так два последних обсуждаемых примера распадаются на две независимые команды — определение пустого блока кода, который ничего не выполнит и унарную операция «плюс» над пустым объектом или массивом.

С массивом, возвращающим пустоту при суммировании (конкатенации) всё ещё проще — в данном случае производится попытка вызвать метод toString, который у массива выводит строку его значений через запятую. Так как значений нет, строка пустая.

В общем, ничего сильно странного не происходит.

2015   javascript   программирование

Как скачать документ из АИС ЦГАСО-2

Самарский архив видимо что-то у себя обновил и предыдущий способ для скачивания документов оттуда работать перестал. Очень жаль, удобство работы с интерфейсом архива оставляет желать лучшего, не говоря о скорости доступа к документам.

С просьбой что-то с этой проблемой сделать, мне написало около десятка человек, сегодня у меня наконец дошли руки посмотреть что изменилось. Как и в прошлый раз надо открыть окно консоли браузера и запустить скрипт (я проверял его в «Хроме»). Плохие новости в том, что скрипт будет работать относительно неспешно — 400 страниц обрабатывается примерно за 5—6 минут.

В конце работы в консоли будет длинная строка, начинающаяся с «dxo.itemsValue» и заканчивающаяся на «];». Её, как и в прошлый раз, надо будет скопировать в файл и передать в параметрах программе.

!function () {
    var id = '[id$=seadragonContainer] div div';
    var bt = '[id$=ForwardBtn]';
    var pages = {};
    var o = document.querySelector(id);

    !function _observe(undefined) {
        var ob = new MutationObserver(function() {
            var imgs = $(id+' img[src*=Pages]:first');
            if (imgs && imgs[0]) {
                var page = imgs[0].src.match(/id=([^&]+)/)[1];
                if (pages[page] == undefined) {
                    pages[page] = true;

                    ob.disconnect();

                    var next = $(bt);
                    if (next && next[0]) {
                        _observe();
                        next[0].click();
                    } else {
                        console.clear();
                        console.log("dxo.itemsValue=['" + Object.keys(pages).join("','")+"'];");
                    }
                }
            }
        });

        ob.observe(o, { childList: true, attributes: true, subtree: true });
    }();

    o.setAttribute('start', true);
}();

Вообще, можно было бы заморочиться и сильно ускорить сбор данных, но я не буду этого делать — меня результат вполне устраивает.

Внимание: скрипт должным образом я ещё не протестировал (просто не успел), так что на корректную работу пока не рассчитывайте!

Кодировка JSON

Я всегда полагал, что кодировка данных в формате JSON («джейсон») должна быть ЮТФ-8. Оказывается в стандарте указано только, что она должна быть Юникодом. Более того, в стандарте указаны способы определения разных типов кодировок.

Так как первые два символа данных в формате «джейсон» всегда будут в первой половине таблицы ASCII (в самом деле, как не крути, первый символ — «{» или «[», а далее кавычка, буква «f» («false»), «n» («null»), «t» («true») или цифра), то легко угадать в какой именно кодировке встретился Юникод:

00 00 00 xx  UTF-32BE
           00 xx 00 xx  UTF-16BE
           xx 00 00 00  UTF-32LE
           xx 00 xx 00  UTF-16LE
           xx xx xx xx  UTF-8

Как видите каких-либо маркеров для ЮТФ-8 не выделено, то есть во всех остальных случаях считается, что кодировка ЮТФ-8. Я посмотрел встроенные парсеры ПХП и Пайтона, они ни с какими другими кодировками Юникода, помимо ЮТФ-8, по всей видимости, не работают, то есть нарушают стандарт.

2014   javascript   json   программирование

Комментарии в формате JSON

Наткнулся случайно на ссылку, где автора очень изящно решает проблему комментариев в формате «джейсон». Это лучшее решение, которое я только видел (обычно либо выделяют специальный ключ, либо расширяют формат). Только поглядите:

{
  "api_host" : "The hostname of your API server. You may also specify the port.",
  "api_host" : "hodorhodor.com",

  "retry_interval" : "The interval in seconds between retrying failed API calls",
  "retry_interval" : 10,

  "auth_token" : "The authentication token. It is available in your developer dashboard under 'Settings'",
  "auth_token" : "5ad0eb93697215bc0d48a7b69aa6fb8b",

  "favorite_numbers": "An array containing my all-time favorite numbers",
  "favorite_numbers": [19, 13, 53]
}

Он полностью синтаксически верен и разбирается правильным образом во всех языках, по всей видимости.

2014   javascript   json   программирование

Короткий способ определить есть ли поддержка dataURI

Придумал короткий способ определить поддержку data URI в браузере:

<script src="data:text/javascript,self.dataURI=1"></script>

Потом просто проверяете у window свойство dataURI, если оно есть, то есть и поддержка. Способ не работает в IE8 и IE9 — тот и другой не умеют загружать Джаваскрипт этим образом. Собственно, меня это не волнует — мне как раз и нужно определить, что Джаваскрипт так работает, но если вам нужно не это, то должен работать вот такой способ:

<link rel="stylesheet" href="data:text/css,html{font-size:99px}">

То есть устанавливаем у тега HTML какое-нибудь свойство, которое потом в BODY перекроем, а позже, чтобы убедиться, что поддержка дата-ури есть, смоторим что вышло (тут я при помощи jQuery это делаю):

/99/.test($('html').css('font')); // true, если есть поддержка dataURI

Странное с Флешем

Я с «Флешем» в последние годы не сталкивался, но и прежде подобного поведения не наблюдал. В общем, решил я вчера обновить в нашем продукте библиотеку ВебКамДжиЭс, она у нас для получения фотографии с камеры используется. Прежняя была 0.9, а тут я случайно обнаружил, что релиз вышел.

В прежней изображение с камеры получалось через Флеш, а релизная умеет использовать АПИ браузера, если таковое имеется. Правда, в «Сафари», которым я пользуюсь, этого АПИ нет и всё равно используется Флеш. Вот тут-то и столкнулся с трудностями — прежняя версия работала прекрасно, а новая отказывалась — в окне Флеша изображение с камеры есть, но ДжаваСкрипт был уверен, что всё плохо и, самое главное, не мог достучаться до Флеша.

В принципе, можно было откатиться на предыдущую версию, но смущало, что на демо-сайте ВебКама в «Сафари» всё работало нормально. Я попробовал несколько вариантов, прежде чем мне пришла в голову идея посмотреть заголовки запросов. И заметил разницу, показавшуюся несущественной, но всё-таки я решил попробовать её устранить — mime type различался.

У нас сервер отдавал Флеш с типом «application/x-shockwave-flash», а в демо-примере был «binary/octet-stream». Стоило поменять этот заголовок, и всё заработало.

Беглое гугление света не пролило, но если столкнётесь с похожей проблемой, имейте ввиду, возможное решение — смена типа для отдаваемого флеш-ролика.

2014   flash   javascript   safari   программирование

Короткий способ определять IE

А какой сейчас самый короткий способ определять Эксплорер? Я понимаю, что привязываться к браузеру нехорошо, но у меня конкретная задача, которую никак не обойти — нужно проиграть звук в браузере (PCM wave), а ИЕ на запрос «сможешь проиграть?» к тегу AUDIO, говорит maybe. Т. е. давайте сюда свой звук, может и смогу. Я-то знаю, что не сможет — аудиотег в этом браузере «вавки» не играет, нужен EMBED.

Все короткие способы, которые раньше работали (условная компиляция, сравнение вертикального пробела с буквой v, хитрый хак с массивом и прочее) в 11-й версии работать перестали. Даже строку агента поменяли — там теперь нет MSIE.

В общем, я пока остановился на такой версии:

if (top.VBArray) {
    // IE
} else {
    // остальные браузеры
}

Но буду признателен за что-то более короткое или очевидное.

2014   ie   javascript   программирование
Ранее Ctrl + ↓