Пользователь
0,0
рейтинг
24 мая 2011 в 20:39

Разработка → Техники сжатия кода перевод

Джед Шмидт, Томас Фухс и Дастин Диаз — достаточно известные в 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 байт ребята иногда просто творят чудеса. Я думаю, даже опытный программист найдет для себя что-то новое и интересное в их коде.
Перевод: Jed Schmidt
rwz @rwz
карма
1,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (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
      Этот же код в удобочитаемом виде gist.github.com/989440
    • +1
      Простите, промахнулся, см. коммент ниже
  • +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
        поправил
    • +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];...};
    • 0
      for(i=a.length;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.._

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