JavaScript

индекс
245,84

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

Джед Шмидт, Томас Фухс и Дастин Диаз — достаточно известные в 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 байт ребята иногда просто творят чудеса. Я думаю, даже опытный программист найдет для себя что-то новое и интересное в их коде.
+134
24 мая 2011, 20:39
253
rwz

комментарии (121)

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

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

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

Если экономите на спичках или искать нужно в большой строке indexOf использовать правильней.
+2
TheShock #
В данном случае первоочерёдно — это длина строки.
+2
shsmad #
Было бы занятно пройтись по измененному коду JSLint'ом…
+1
markPnk #
Уверен — он вознегодует
+5
pro100tak #
Быстрый запрос к серверу (только push и без возможности ответа):
var i=new Image;
i.src='http://url.here?need=data';
+6
ArtemSmirnov #
(new Image).src='http://url.here?need=data';
+1
pro100tak #
Маньяк :)
+3
TheShock #
Или так:
new Image().src='http://url.here?need=data';
+2
ArtemSmirnov #
Можно еще так.
(c = new Image).src='http://url.here?need=data'
c.src = 'http://url.here?need=otherData'
+6
l2k #

u = 'http://url.here?need=';
(c = new Image).src= u+'data'
c.src = u+'otherData'
+4
azproduction #
В пути к ресурсам не обязательно указывать протокол (будет установлен текущий). Не уверен, что работает во всех браузерах. Для URL можно использовать короткие ссылки — j.mp (короче j.mp только свой домен первого уровня)
// "//j.mp/hW9b6U" === "http://yandex.ru/favicon.ico"
new Image().src='//j.mp/hW9b6U';
+4
bolk #
Это работает во всех браузерах. Это часть RFC.
+2
homm #
Да, в браузерах работает, а вот тупые боты, в том числе вконтакта и Касперского RFC не читали, все время долбятся в 404-е, считая домен частью относительного url.
+8
azproduction #
Как дополнительный эффект статьи мы получили эффективный способ вычисления бота! :)
+9
shergin #
В ответ можно получить ширину и высоту картинки. Иногда этого достаточно.
+1
bolk #
Почему без возможности. Можно вернуть error (и обработать onerror или onload).
+1
pro100tak #
Я имел ввиду — осмысленный ответ (строку, JSON и т.д.). Но так — да: проверить наличие атрибута width либо вешаться на onload/onerror. Это только проверка доставки данных, но полноценного транспорта не выйдет. Но, плюсом является абсолютная кроссдоменность :)
+1
bolk #
Осмысленное что-то можно в cookie передать.
+1
pro100tak #
Даёшь аякс транспорт в 1000 байт!!! :)
+6
azproduction #
Хватит и 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
azproduction #
Парсер, когда же ты наконец перестанешь переделывать ) в коде на ©?
+2
TheShock #
Rulez!
+1
Olostan #
158 символов для кроссброузерного — чуть чуть не хватает для проекта «140байт» :(
+1
Mixailo #
Как развлечение одобряю, но выпускающих такое в продакшен надо драть нещадно.
0
easyman #
И заставить переписать так, чтобы другие саппортить могли.
+9
Keler #
Неделя JavaScript прекрасна:)
+9
TheShock #
Уже вторая пошла)) Наконец-то неделя чего-то не оффтопного, не так ли?)
+2
homm #
Используйте еще более короткие способы записи undefined
function a(a){if(a==[]._){...};c=[]._}
function a(a,b){if(a==b){...};c=b}
+1
TheShock #
А чем плохо?
if (a == null)
+1
bolk #
a==b короче.
+1
TheShock #
согласен, но не вижу смысла в []._
+1
bolk #
Я тоже не вижу. Но вижу смысл в a === []._
+1
azproduction #
А я вижу — путать людей не посвященных в JavaScript :) Вот вам quiz:
var N = 3;
while (1..N) {
    alert(0); // <<< Сколько раз отработает alert?
}

// или вот так
var N = 3;
while (a in [1..N]) {
    alert(a); // <<< Сколько раз отработает alert и что выведет?
}
+1
bolk #
Я очень долго пытался понять что же здесь написано :) Наконец догадался. Но спасибо, мозг мне коротнуло :) Правда надо ещё «а» описать, иначе операция in не сработает.
0
Keler #
в JavaScript есть диапазоны как в Ruby!!?
0
azproduction #
Нет. Это обман зрения :) Давайте разберем: 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
ich #
вместо длинного undefined можно использовать более симпатичное 0..O
0
romy4 #
0..0 нельзя, и 1..1 нельзя. но можно 0[0] и 1[1]
0
TheShock #
там буква, а не цифра.
0
ich #
совершенно верно
+1
Olostan #
как бы null и undefined — две огромных разницы
+1
TheShock #
Не такие уж и большие
null == undefined; // true
undefined == null; // true
null == 0;      // false
undefined == 0; // false
+1
Olostan #
А в ракурсе typeof? :)

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


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

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

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

Тоже получается не такая уж и большая разница :)
+3
TheShock #
На самом деле это переход на личности. То, что нестрогое сравнение где-то имеет не совсем логичный результат — ничего не значит. Оно семантически верно сравнивает с 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
rwz #
Что-то я не уловил тут перехода на личности. А ты, по-моему, слишком напрягся от очередного ничего не значащего шуточного коммента. :)

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

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

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

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

0
s0rr0w #
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
TheShock #
Между прочим, ко мне только что пришло озарение, как создавать и использовать короткие функции (только для современных браузеров).

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

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

Плохо отслеживаю, что нового в Firefox:(
+1
s0rr0w #
Этому «новому» более трех лет уже. Может даже около 5, не помню точно…
+1
TheShock #
Осень 2008, так что 2 с половиной года.
0
s0rr0w #
Ну, предварительные документы появились немного раньше, чем вышел FF3.0
+1
bolk #
Вообще парни как-то маловато способов описали.
+1
ArtemSmirnov #
Глюкнутый но рабочий польский калькулятор, всего две команды + и -. 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
azproduction #
Самый короткий и кросс-браузерный код для определения браузера в 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
azproduction #
Этот же код в удобочитаемом виде gist.github.com/989440
+1
YAAP #
Простите, промахнулся, см. коммент ниже
+1
YAAP #
c false
f false
i true
o false
s false


Это результаты для ФФ 3.6.17 ;)
+1
YAAP #
А все потому, что
console.log(this.Worker); // undefined
+2
YAAP #
А все потому, что код в консоли выполняется. Непосредственно в браузере все работает.
+1
azproduction #
Очень странно. Воркеры появились в Firefox 3.5, да и я проверял их наличие goo.gl/tD1jr Вы случайно не используете IE Tab?
+2
YAAP #
Нет, не использую, просто код запустил выполнятся в консоли firebug, где, как я понимаю, этого самого воркера и нет.
+1
VolCh #
Читаю топик и ощущение «дежа вю». Потом понял — это же «Совершенный код» в формате «вредных советов» :D
+1
Stalker_RED #
это можно применить в обфускаторах и во всяких сжимателях.
к примеру !0 и !1 вместо true и false — это круто ведь!
+2
Markel #
Если 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
TheShock #
~-a&&console.log("not one")
+1
rwz #
поправил
+1
azproduction #
ещё вариант с xor'ом
a^1&&console.log("not one");
// читабельнее чем ~-a
+1
dbelka #
1 in arguments||(cb=alert) // до
arguments[1]||(cb=alert) // после
0
rwz #
Не работает, когда аргумент — 0, '', null, undefined, [] и что угодно другое, что дает false при приведении.
0
dbelka #
согласен
if 1 in arguments — проверка на существование
if arguments[1] — проверка на не пустое значение
0
lahmatiy #
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
josser #
еще вариант итерации по массиву:
i=a.length; while(i--){b=a[i];...};
0
TheShock #
for(i=a.length;i--;){b = a[i];..}
–1
petergreen #
полнейший идиотизм, когда же этот ** твитер сдохнет со своим числом 140
бре-
э-
эд
0
romy4 #
из коротких способов записи 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
romy4 #
0[0] достаточно быстрее, чем 1.._

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