Техники сжатия кода

https://github.com/jed/140bytes/wiki/Byte-saving-techniques
  • Перевод
Джед Шмидт, Томас Фухс и Дастин Диаз — достаточно известные в JavaScript-коммьюнити ребята в последнее время нашли себе новую развлекуху — писать полезные штуки размером не больше одного твита, то есть 140 байт. Даже домен зарегали — 140byt.es, куда приглашаются все желающие попробовать свои силы в написании супер-компактных функций.

Естественно, в ход идут все самые изощренные способы и техники уменьшения размера исходника. У них есть вики-страничка с советами, которую я и решил перевести.

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

Итак.

Arguments


Используйте однобуквенные позиционные аргументы в алфавитном порядке


Поскольку аргументы функции должны быть как можно более короткими, и скорее всего будут использованы по несколько раз во время выполнения, проще рассматривать их с точки зрения позиции и именовать в алфавитном порядке, вместо того, чтобы пытаться давать им сколько-либо осмысленные имена.
function(t,d,v,i,f){...} // до
function(a,b,c,d,e){...} // после


Проверяйте наличие аргументов вместо длины


Можно использовать in для проверки наличия аргумента.
arguments.length>1||(cb=alert) // до
1 in arguments||(cb=alert)     // после


Переменные


Используйте «лишние» аргументы вместо var


Можно сэкономить несколько байт указав лишний аргумент в функции, вместо объявления переменной с помощью var:
function(a){var b=1;...} // до
function(a,b){b=1;...}   // после


Используйте переменные по несколько раз


setTimeout(function(){for(var i=10;i--;)... }, a) // до
setTimeout(function(){for(a=10;a--;)... }, a)     // после


Используйте присваивание там, где это возможно


Поскольку оператор присваивания возвращает присваиваемое значение, можно использовать присваивание и проверку одновременно:
a=this.localStorage;if(a){...} // до
if(a=this.localStorage){...}   // после


Используйте массив чтобы поменять местами переменные


Массив можно использовать как временное хранилище, чтобы не объявлять лишнюю переменную.
var a=1,b=2,c;c=a;a=b;b=c // до
var a=1,b=2;a=[b,b=a][0]  // после


Используйте приведение типов при сложении


Приведение типов в JS работает весьма странно и является одним из самых распространенных источником багов. Тем не менее, его можно использовать разными интересными способами для уменьшения размеров кода.
Наример, в реализации pubsub Джед Шмидт декрементировал переменную с отрицательным числом, а затем прибавлял ее к строке, получая что-то вида "somestring-123".
После этого в другом месте использовал .split('-') для получения исходной строки.

Циклы


Опускайте тело цикла


Зачастую можно реализовать всю логику внутри условий и сэкономить на теле цикла.
Хороший пример этого подхода можно посмотреть в функции timeAgo.

Используйте for вместо while


for и while обычно занимают одинаково количество байт, но for позволяет получить больший контроль и больше возможностей для присваивания.
while(i--){...} // до
for(;i--;){...} // после

i=10;while(i--){...} // до
for(i=10;i--;){...}  // после


Используйте быструю итерацию по «правдивым» массивам


Если у вас есть массив, все члены которого заведомо приводятся к true, можно использовать более короткую запись цикла:
for(a=[1,2,3,4,5],l=a.length,i=0;i<l;i++){b=a[i];...} // до
for(a=[1,2,3,4,5],i=0;b=a[i++];){...}                 // после


Используйте for..in с присваиванием для получения ключей объектов


a=[];for(b in window)a.push(window[b]) // до
a=[];i=0;for(a[i++]in window);         // после


Операторы


Выучите приоритет операторов


Эти знания могут помочь неплохо сэкономить на скобках.
Начать можно с изучения этой статьи на сайте Mozilla.

Используйте ~ c indexOf


hasAnF="This sentence has an f.".indexOf("f")>=0 // до
hasAnF=~"This sentence has an f.".indexOf("f")   // после


Используйте запятую для последовательного выполнения операторов вместо блока


with(document){open();write("hello");close()} // до
with(document)open(),write("hello"),close()   // после


Используйте более короткие способы записи undefined


Вместо undefined можно использовать []._ или void 0.
Есть варианты ""._, 1.._ и [][0], но они намного медленнее.

Удаляйте необязательные пробелы перед операторами


Иногда пробелы после операторов можно безболезненно удалить.
typeof [] // до
typeof[]  // после


Числа


Используйте ~~ или 0| вместо Math.floor


rand10=Math.floor(Math.random()*10) // до
rand10=0|Math.random()*10           // после


Используйте экспоненциальный формат для больших круглых чисел


million=1000000 // до
million=1e6     // после


Используйте побитовые сдвиги для больших бинарных чисел


color=0x100000 // до
color=1<<20    // после


Используйте 1/0 вместо Infinity


Это короче. Кроме того, делить на нуль всегда весело.
[Infinity,-Infinity] // до
[1/0,-1/0]           // после


Используйте «ложность» нуля


Вместо сравнивания чисел иногда короче свести значение к нулю и проверить его истинность.
a==1||console.log("not one") // до
~-a&&console.log("not one")  // после


Используйте ~ чтобы изменить любое значение на единицу


В сочетании с унарным минусом это дает возможность, например, инкрементировать любую, даже еще не определенную переменную.
// i = undefined
i=i||0;i++ // до
i=-~i      // после


Строки


Разбивайте строки с помощью нуля


Можно сэкономить два байта при разбиении строк методом split, если в качестве разделителя использовать нуль:
'alpha,bravo,charlie'.split(',') // до
'alpha0bravo0charlie'.split(0)   // после


Используйте браузерный метод link


Строки в браузерах имеют не очень известный метод link, который создает html-ссылку.
html="<a href='"+url+"'>"+text+"</a>" // до
html=text.link(url)                   // после


Используйте методы replace и exec для итерации по строкам


Эти методы позволяют передавать функцию в качестве второго аргумента. Этим можно воспользоваться для удобной итерации по строке.
Примеры использования: templates и UUID.

Используйте массивы для создания простых строк


for(a="",i=32;i--;)a+=0 // до
a=Array(33).join(0)     // после


Регулярные выражения


Используйте {n} для укорачивания рeгулярных выражений. Например /\d{3}/ вместо /\d\d\d/. И наоборот /\d\d/ вместо /\d{2}/.

Можно использовать eval вместо конструктора регулярки:
r=new RegExp("{"+p+"}","g") // до
r=eval("/{"+p+"}/g")        // после


Boolean


Используйте ! с цифрами для создания true и false.
[true,false] // до
[!0,!1]      // после


Функции


Используйте именованные функции для рекурсии вместо циклов


Зачастую это получается короче, поскольку позволяет протаскивать значения через стек, без лишних переменных.
В качестве примера функция walk.

Используйте именованные функции для хранения состояния


Если надо хранить состояние между вызовами функции, функцию можно использовать как объект и хранить данные в ее свойствах:
function(i){return function(){console.log("called "+(++i)+" times")}}(0) // до
(function a(){console.log("called "+(a.i=-~a.i)+" times")})              // после
0,function a(){console.log("called "+(a.i=-~a.i)+" times")}              // еще вариант


Опускайте скобки при вызове конструктора без аргументов


now = +new Date() // до
now = +new Date   // после


Опускайте ключевое слово new там, где это возможно


Некоторым конструкторам вовсе не обязательно ключевое слово new.
r=new Regexp(".",g) // до
r=Regexp(".",g)     // после

l=new Function("x","console.log(x)") // до
l=Function("x","console.log(x)")     // после


Оператор return


Когда надо вернуть что-то отличное от переменной, ставить пробел после return не обязательно.
return ['foo',42,'bar']; // до
return['foo',42,'bar'];  // после
return {x:42,y:417}; // до
return{x:42,y:417};  // после
return .01; // до
return.01;  // после


Пока все.

Вообще, рекомендую ознакомиться с плодами их творчества. В попытках уместить сложные вещи в 140 байт ребята иногда просто творят чудеса. Я думаю, даже опытный программист найдет для себя что-то новое и интересное в их коде.
Поделиться публикацией
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама
Комментарии 121
  • –8
    «Используйте более короткие сособы записи undefined».
    Поправьте, очепятку.
    • +1
      Поправил, спасибо.
      • –3
        Ещё «еденица».
    • +2
      azproduction писал прикольную статью на эту тему.
      • +3
        Многие трюки вполне нормально будут смотреться и в повседневной разработке.
        • +15
          если использовать эти методы в крупных блоках кода, вы не только сэкономите байтики, но и гарантированно обеспечите себя и других разработчиков мигренью при дальнейшей работе с кодом :)

          хотя в общем, очень даже интересная статья, познавательная.
          • +2
            Используйте UglifyJS для первичного сжатия кода — он сделает половину работы за вас.
            • +1
              Uglify применяет лишь самые примитивные и теоретически безопасные методы сжатия. Здесь в основном перечислены post/pre-uglifier советы, базирующиеся на изначальной компоновке и построении кода. Аглифай не обладает интеллектом, чтобы применять подобные штуки.

              И про более короткий undefined uglify тоже не знает :)
              • +1
                тут идет вопрос чисто о спортивном интересе — сделать код минимальным
                посему автоматические штуки не пройдут
              • +4
                Еще давно в моей голове маразм крепчал очень сильно и я писал:
                foo|=evt.keyCode==34
                Вместо
                if(evt.keyCode==34)foo=true;
                • +3
                  Ещё очень много можно интересного сделать, если складывать с undefined и т.п.
                  • +4
                    Ещё некоторые большие числа занимают меньше в hex: 0x607E416AD57E60
                    • 0
                      Если использовать алфавит кодирования больше алфавита исходной информации — меньше получится символов.
                      • +1
                        Для этого таких чисел должно быть много, ведь ещё декодировать надо.
                        • +4
                          Декодировщик небольшой, но да — чисел надо много:
                          parseInt('ZZZZZZZZZZZZZ', 36);
                          //170581728179578200000
                          
                          • 0
                            Ого, я и позабыл, что parseInt так умеет.
                    • 0
                      а еще можно написать
                      undefined = "something" //happy debugging
                      
                    • +8
                      Вот ещё нашёл — поиск в строке
                      var a = 'some string';
                      if (!~a.search('b')) ...
                      
                      • +2
                        О, ради этого коммента закинул даже сам топик в мемориз!
                        • +5
                          Так можно же комментарии в меморизы кидать.
                          • +2
                            По-моему скромному мнению, разумнее закинуть в мемориз одну статью с большим количеством толковых комментариев, чем множество комментариев к одной статье.
                        • 0
                          IndexOf быстрее чем search, как я понимаю это из-за того что в search'е можно использовать регулярные выражения.

                          Если экономите на спичках или искать нужно в большой строке indexOf использовать правильней.
                          • +2
                            В данном случае первоочерёдно — это длина строки.
                        • +2
                          Было бы занятно пройтись по измененному коду JSLint'ом…
                          • НЛО прилетело и опубликовало эту надпись здесь
                          • +5
                            Быстрый запрос к серверу (только push и без возможности ответа):
                            var i=new Image;
                            i.src='http://url.here?need=data';
                            
                            • +6
                              (new Image).src='http://url.here?need=data';
                              • +1
                                Маньяк :)
                                • +3
                                  Или так:
                                  new Image().src='http://url.here?need=data';
                                  
                                  • +2
                                    Можно еще так.
                                    (c = new Image).src='http://url.here?need=data'
                                    c.src = 'http://url.here?need=otherData'
                                    
                                    • +6
                                      
                                      u = 'http://url.here?need=';
                                      (c = new Image).src= u+'data'
                                      c.src = u+'otherData'
                                      
                                  • +4
                                    В пути к ресурсам не обязательно указывать протокол (будет установлен текущий). Не уверен, что работает во всех браузерах. Для URL можно использовать короткие ссылки — j.mp (короче j.mp только свой домен первого уровня)
                                    // "//j.mp/hW9b6U" === "http://yandex.ru/favicon.ico"
                                    new Image().src='//j.mp/hW9b6U';
                                    • +4
                                      Это работает во всех браузерах. Это часть RFC.
                                      • +2
                                        Да, в браузерах работает, а вот тупые боты, в том числе вконтакта и Касперского RFC не читали, все время долбятся в 404-е, считая домен частью относительного url.
                                        • +8
                                          Как дополнительный эффект статьи мы получили эффективный способ вычисления бота! :)
                                  • +9
                                    В ответ можно получить ширину и высоту картинки. Иногда этого достаточно.
                                    • +1
                                      Почему без возможности. Можно вернуть error (и обработать onerror или onload).
                                      • +1
                                        Я имел ввиду — осмысленный ответ (строку, JSON и т.д.). Но так — да: проверить наличие атрибута width либо вешаться на onload/onerror. Это только проверка доставки данных, но полноценного транспорта не выйдет. Но, плюсом является абсолютная кроссдоменность :)
                                        • +1
                                          Осмысленное что-то можно в cookie передать.
                                          • +1
                                            Даёшь аякс транспорт в 1000 байт!!! :)
                                            • +6
                                              Хватит и 118
                                              function xhr(m,u,c,x){with(new XMLHttpRequest)onreadystatechange=function(x){readyState^4||c(x.target)},open(m,u),send©}

                                              Кросс-браузерный немного длиннее
                                              function xhr(m,u,c,x){with(new(this.XMLHttpRequest||ActiveXObject)("Microsoft.XMLHTTP"))onreadystatechange=function(x){readyState^4||c(x)},open(m,u),send©}

                                              Usage:
                                              xhr('get', '//ya.ru/favicon.ico', function(xhr){console.dir(xhr)});
                                              • +2
                                                Парсер, когда же ты наконец перестанешь переделывать ) в коде на ©?
                                                • +2
                                                  Rulez!
                                                  • +1
                                                    158 символов для кроссброузерного — чуть чуть не хватает для проекта «140байт» :(
                                        • +1
                                          Как развлечение одобряю, но выпускающих такое в продакшен надо драть нещадно.
                                          • 0
                                            И заставить переписать так, чтобы другие саппортить могли.
                                          • +9
                                            Неделя JavaScript прекрасна:)
                                            • +9
                                              Уже вторая пошла)) Наконец-то неделя чего-то не оффтопного, не так ли?)
                                            • +2
                                              Используйте еще более короткие способы записи undefined
                                              function a(a){if(a==[]._){...};c=[]._}
                                              function a(a,b){if(a==b){...};c=b}
                                              • +1
                                                А чем плохо?
                                                if (a == null)
                                                
                                                • +1
                                                  a==b короче.
                                                  • +1
                                                    согласен, но не вижу смысла в []._
                                                    • +1
                                                      Я тоже не вижу. Но вижу смысл в a === []._
                                                      • +1
                                                        А я вижу — путать людей не посвященных в JavaScript :) Вот вам quiz:
                                                        var N = 3;
                                                        while (1..N) {
                                                            alert(0); // <<< Сколько раз отработает alert?
                                                        }
                                                        
                                                        // или вот так
                                                        var N = 3;
                                                        while (a in [1..N]) {
                                                            alert(a); // <<< Сколько раз отработает alert и что выведет?
                                                        }
                                                        
                                                        • +1
                                                          Я очень долго пытался понять что же здесь написано :) Наконец догадался. Но спасибо, мозг мне коротнуло :) Правда надо ещё «а» описать, иначе операция in не сработает.
                                                          • 0
                                                            в JavaScript есть диапазоны как в Ruby!!?
                                                            • 0
                                                              Нет. Это обман зрения :) Давайте разберем: var N = 3, a; while (a in [1..N]) ...

                                                              1. мы у 1.0 (1.) пытаемся получить свойство N через точечную нотацию — его нет, поэтому 1..N возвратит undefined. Переменная N объявлена для отвлечения и никакой нагрузки не несет.
                                                              2. в итоге мы имеем массив [undefined] - (0: undefined),
                                                              3. дальше мы пытаемся узнать, а есть ли что-то с ключем undefined (a===undefined) в нашем массиве — a in [undefined] получаем false.

                                                              Сколько раз отработает alert?: Ответ в обоих случаях — 0
                                                            • 0
                                                              вместо длинного undefined можно использовать более симпатичное 0..O
                                                              • 0
                                                                0..0 нельзя, и 1..1 нельзя. но можно 0[0] и 1[1]
                                                                • 0
                                                                  там буква, а не цифра.
                                                                  • 0
                                                                    совершенно верно
                                                      • +1
                                                        как бы null и undefined — две огромных разницы
                                                        • +1
                                                          Не такие уж и большие
                                                          null == undefined; // true
                                                          undefined == null; // true
                                                          null == 0;      // false
                                                          undefined == 0; // false
                                                          
                                                          • +1
                                                            А в ракурсе typeof? :)

                                                            Ну окромя шуток семантика (или точнее когда значения являются/становятся нуллами, а когда андефами) действительно отличается.
                                                            • +1
                                                              Я отвечал на комментарий
                                                              • +1
                                                                * Я отвечал на комментарий
                                                                if(a==[]._)
                                                                

                                                                В таком виде разницы действительно нету.
                                                                Между прочим, как раз, семантика очень похожа и многие фреймворки используют именно == null в силу лаконичности и очевидности.

                                                                jQuery:
                                                                get: function( num ) {
                                                                	return num == null ?
                                                                		// Return a 'clean' array
                                                                		this.toArray() :
                                                                
                                                                		// Return just the object
                                                                		( num < 0 ? this[ this.length + num ] : this[ num ] );
                                                                },
                                                                


                                                                MooTools:
                                                                • +1
                                                                  Да что ж такое:
                                                                  Function.prototype.overloadSetter = function(usePlural){
                                                                  	var self = this;
                                                                  	return function(a, b){
                                                                  		if (a == null) return this;
                                                                  		// ...
                                                                  	};
                                                                  };
                                                                  
                                                                  • +1
                                                                    И, вообще не понимаю, зачем столь близкие по смыслу значения. Оставили бы один null — его бы хватило с головой.
                                                                    • +1
                                                                      Иногда возникают ситуации, когда нужно чётко отличать задание «пустого» значения и не задание вообще никакого и в некоторых ЯП undefined значения не хватает.
                                                                      • +1
                                                                        А как отличить задание undefined значения и вообще никакого? ;)
                                                                        • +1
                                                                          С массивами, например, прокатывает такая штука
                                                                          0 in [undefined] // true
                                                                          0 in []          // false
                                                                          
                                                                          • +1
                                                                            Аналогично прокатывает с null ;)
                                                                            0 in [null] // 0
                                                                            


                                                                            Имхо, undefined — это тот же null, но просто ещё более null. =)))
                                                                            • +2
                                                                              Чтобы не путать читателей уточню:
                                                                              null — примитивное значение, представляющее нулевую, пустую, не существующую ссылку
                                                                              undefined — примитивное значение, которое получает каждая перемененная по умолчанию (когда переменная не имеет значение)
                                                                              void — оператор (т.е. скобки не нужны), выполняющий выражение и всегда возвращающий undefined

                                                                              В JavaScript, кстати, каждая функция по умолчанию возвращает undefined
                                                                              (function(){}()) === void 0 // true
                                                                          • +1
                                                                            Запретить присваивать undefined? :)
                                                                            • +1
                                                                              Как?)
                                                                              • +1
                                                                                Синтаксисом оператора присваивания?
                                                                                • +1
                                                                                  Эээ. А можно на примере?
                                                                        • 0
                                                                          Если вернуться к «истокам», когда переменные имели строгую типизацию, объявление переменной влекло за собой выделение памяти или запись в таблицу идентификаторов. undefined переменные были те, объявления которых вообще не было. После объявления переменной, она равнялась null, типа вообще ничего никогда не записывали в память, но информация о переменной уже записана в таблицу переменных.

                                                                          Варианты реализации могли быть разными, но в общем примерно так. Аналогичное поведение сделали в JS, но разницы особо в них нет из-за условий сравнения и приведения типов.
                                                                  • +2
                                                                    Сравнение через == не в счет, поскольку, например
                                                                    "" == [[[[[,]]]]] // true
                                                                    

                                                                    Тоже получается не такая уж и большая разница :)
                                                                    • +3
                                                                      На самом деле это переход на личности. То, что нестрогое сравнение где-то имеет не совсем логичный результат — ничего не значит. Оно семантически верно сравнивает с null. Например, мы хотим удостовериться, что в конструктор передан аргумент:
                                                                      function Point (x, y) {
                                                                      	if (typeof x == 'undefined' || typeof y == 'undefined') throw new TypeError();
                                                                      	this.x = x;
                                                                      	this.y = y;
                                                                      };
                                                                      // или даже
                                                                      function Point (x, y) {
                                                                      	if (x === undefined || y === undefined) throw new TypeError();
                                                                      	this.x = x;
                                                                      	this.y = y;
                                                                      };
                                                                      // vs
                                                                      function Point (x, y) {
                                                                      	if (x == null || y == null) throw new TypeError();
                                                                      	this.x = x;
                                                                      	this.y = y;
                                                                      };
                                                                      

                                                                      Мне кажется, что последний пример намного логичнее и лаконичнее, тем более, что в данном примере нельзя воспользоваться arguments.length:

                                                                      function PointFactory (x, y) {
                                                                      	return new Point(x, y);
                                                                      };
                                                                      
                                                                      • +1
                                                                        Что-то я не уловил тут перехода на личности. А ты, по-моему, слишком напрягся от очередного ничего не значащего шуточного коммента. :)

                                                                        Тем не менее бывают случаи, когда надо отличить null от undefined. И тогда []._ вполне себе будет уместен.

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

                                                                        Касательно твоего примера полностью соласен — последний вариант выглядит наиболее лаконично.
                                                                        • +1
                                                                          На счёт перехода на личности. Я имел ввиду не свою личность, а личность нестрогого сравнения =))) Ну типа, раз он неправильно сравнивает строки и массивы, что он вообще знает в сравнениях)
                                                                          • +3
                                                                            лол

                                                                            Ну тогда при следующей встрече попрошу прощения у личности нестрого сравнения. :)
                                                                    • 0
                                                                      Первые два сравнения — исключительные ситуации

                                                                      • 0
                                                                        ECMA-262
                                                                        Section 11.9.3
                                                                        If x is null and y is undefined, return true.
                                                                        If x is undefined and y is null, return true
                                                              • +1
                                                                Между прочим, ко мне только что пришло озарение, как создавать и использовать короткие функции (только для современных браузеров).

                                                                with({ get a () { return Math.random() } }) {
                                                                  alert(a)
                                                                }
                                                                
                                                                • +1
                                                                  Тоже не во всех браузерах, но ещё короче:
                                                                  with({get a()Math.random()}) {
                                                                    alert(a)
                                                                  }
                                                                  • +1
                                                                    Это уже только в Fx =( А полные геттеры — ещё и в Хроме, Опере, Ие9
                                                                  • +1
                                                                    Расскажите, что это?)
                                                                    • +1
                                                                      Javascript Getter в совокупности с with =)
                                                                      • +1
                                                                        Все, теперь понял. Круто:)
                                                                      • +1
                                                                        А azproduction комментом ниже использовал Expression closures из javascript 1.8, который поддерживается только Firefox3+

                                                                        Подробнее: habrahabr.ru/blogs/javascript/113344/
                                                                        • +1
                                                                          На фоне вашего примера уже понятно, что это:)

                                                                          Плохо отслеживаю, что нового в Firefox:(
                                                                          • +1
                                                                            Этому «новому» более трех лет уже. Может даже около 5, не помню точно…
                                                                            • +1
                                                                              Осень 2008, так что 2 с половиной года.
                                                                              • 0
                                                                                Ну, предварительные документы появились немного раньше, чем вышел FF3.0
                                                                    • +1
                                                                      Вообще парни как-то маловато способов описали.
                                                                      • +1
                                                                        Глюкнутый но рабочий польский калькулятор, всего две команды + и -. 120 байт
                                                                        (function(e,s,i,o){
                                                                        while(o=e[i++])
                                                                                s.push(
                                                                                    +o?+o:
                                                                                    s.pop()*(o=='+'?1:-1)+s.pop()
                                                                                   );
                                                                            alert(s.pop())}
                                                                        )(prompt().split(' '),[],0);
                                                                        
                                                                        (function(a,b,c,d){while(d=a[c++])b.push(+d?+d:b.pop()*(d=="+"?1:-1)+b.pop());alert(b.pop())})
                                                                        (prompt().split(" "),[],0)
                                                                        
                                                                        • +9
                                                                          Самый короткий и кросс-браузерный код для определения браузера в 83 байта!
                                                                          w=this.Worker,l=w&&(w.prototype+"").length,b={f:l==36,o:l==33,s:l==24,c:l==15,i:!w}

                                                                          Формат переменной b:
                                                                          { 
                                                                              f: {true|false}, // Firefox
                                                                              o: {true|false}, // Opera
                                                                              s: {true|false}, // Safari
                                                                              c: {true|false}, // Chrome
                                                                              i: {true|false}  // IE любой
                                                                          }
                                                                          

                                                                          Можно немного короче, но тогда не будет булеанов. Код использует особенность имени прототипа воркера, которую я описал тут. Надо будет выложить на 140byt.es
                                                                        • +1
                                                                          c false
                                                                          f false
                                                                          i true
                                                                          o false
                                                                          s false


                                                                          Это результаты для ФФ 3.6.17 ;)
                                                                          • +1
                                                                            А все потому, что
                                                                            console.log(this.Worker); // undefined
                                                                            • +2
                                                                              А все потому, что код в консоли выполняется. Непосредственно в браузере все работает.
                                                                            • +1
                                                                              Очень странно. Воркеры появились в Firefox 3.5, да и я проверял их наличие goo.gl/tD1jr Вы случайно не используете IE Tab?
                                                                              • +2
                                                                                Нет, не использую, просто код запустил выполнятся в консоли firebug, где, как я понимаю, этого самого воркера и нет.
                                                                            • +1
                                                                              Читаю топик и ощущение «дежа вю». Потом понял — это же «Совершенный код» в формате «вредных советов» :D
                                                                              • +1
                                                                                это можно применить в обфускаторах и во всяких сжимателях.
                                                                                к примеру !0 и !1 вместо true и false — это круто ведь!
                                                                              • +2
                                                                                Если a = 2
                                                                                a==1||console.log("not one") // до
                                                                                ~-a||console.log("not one")  // после
                                                                                

                                                                                Вывод «not one» будет только в первом случае

                                                                                Наверное имелось ввиду что-то подобное:
                                                                                if(a!=1) console.log("not one") // до
                                                                                if(~-a) console.log("not one")  // после
                                                                                

                                                                                Тогда в обоих случаях будет вывод «not one»
                                                                                • +2
                                                                                  ~-a&&console.log("not one")
                                                                                  
                                                                                • +1
                                                                                  ещё вариант с xor'ом
                                                                                  a^1&&console.log("not one");
                                                                                  // читабельнее чем ~-a
                                                                                • +1
                                                                                  1 in arguments||(cb=alert) // до
                                                                                  arguments[1]||(cb=alert) // после
                                                                                  • 0
                                                                                    Не работает, когда аргумент — 0, '', null, undefined, [] и что угодно другое, что дает false при приведении.
                                                                                    • 0
                                                                                      согласен
                                                                                      if 1 in arguments — проверка на существование
                                                                                      if arguments[1] — проверка на не пустое значение
                                                                                  • 0
                                                                                    a=[];for(b in window)a.push(window[b]) // до
                                                                                    a=[];i=0;for(a[i++]in window); // после

                                                                                    Не эквивалентные записи, в первой получим значения, а во второй ключи.
                                                                                    Если исправить
                                                                                    a=[];for(b in window)a.push(b) // до

                                                                                    то строки будут одинаковой длины :) но второй вариант оригинален…
                                                                                    Так же стоит заметить, что многие из описанных «оптимизаций» делает Closure compiler
                                                                                    • 0
                                                                                      еще вариант итерации по массиву:
                                                                                      i=a.length; while(i--){b=a[i];...};
                                                                                    • –1
                                                                                      полнейший идиотизм, когда же этот ** твитер сдохнет со своим числом 140
                                                                                      бре-
                                                                                      э-
                                                                                      эд
                                                                                      • 0
                                                                                        из коротких способов записи undefined самым быстрым оказался void 0, потом почти так же 0[0]
                                                                                        algos = [["void 0",  function(){void 0;}]	,["\"\"._", function(){""._;}]	
                                                                                        ,["1.._",    function(){1.._;}]	,["0[0]",    function(){0[0];}]];
                                                                                        
                                                                                        var tms=[];
                                                                                        
                                                                                        for(i in algos)
                                                                                        {
                                                                                           tms[i] = +new Date();
                                                                                           for(var k=0;k<10000000;k++)
                                                                                           {
                                                                                                algos[i][1]();
                                                                                           }
                                                                                           tms[i] = (+new Date()) - tms[i];
                                                                                        }
                                                                                        
                                                                                        • 0
                                                                                          0[0] достаточно быстрее, чем 1.._

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