Pull to refresh

Comments 121

«Используйте более короткие сособы записи undefined».
Поправьте, очепятку.
Поправил, спасибо.
Многие трюки вполне нормально будут смотреться и в повседневной разработке.
если использовать эти методы в крупных блоках кода, вы не только сэкономите байтики, но и гарантированно обеспечите себя и других разработчиков мигренью при дальнейшей работе с кодом :)

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

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

Если экономите на спичках или искать нужно в большой строке indexOf использовать правильней.
В данном случае первоочерёдно — это длина строки.
Было бы занятно пройтись по измененному коду JSLint'ом…
UFO just landed and posted this here
Быстрый запрос к серверу (только push и без возможности ответа):
var i=new Image;
i.src='http://url.here?need=data';
Или так:
new Image().src='http://url.here?need=data';
Можно еще так.
(c = new Image).src='http://url.here?need=data'
c.src = 'http://url.here?need=otherData'

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

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

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


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

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

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

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

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

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

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

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

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

with({ get a () { return Math.random() } }) {
  alert(a)
}
Тоже не во всех браузерах, но ещё короче:
with({get a()Math.random()}) {
  alert(a)
}
Это уже только в Fx =( А полные геттеры — ещё и в Хроме, Опере, Ие9
Расскажите, что это?)
Все, теперь понял. Круто:)
На фоне вашего примера уже понятно, что это:)

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


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

Articles