Какие общие советы у вас есть для игры в гольф на JavaScript? Я ищу идеи, которые могут быть применены к проблемам с гольфом в коде, которые, по крайней мере, несколько специфичны для JavaScript (например, «удалить комментарии» - это не ответ).
Примечание. См. Также Советы по игре в гольф в ECMAScript 6 и выше.
code-golf
tips
javascript
mellamokb
источник
источник
var
)? И должен ли гольф-код JavaScript быть функцией или выводить что-то напрямую? Я искренне думаю, что это может иметь большое значение.Ответы:
Fancy For Loops
Вы можете использовать стандарт для цикла нестандартными способами
по существу эквивалентно:
так что хороший трюк - написать код с
while
циклом, а затем разбить его наa,b,c
части вfor
цикле.Несколько примеров, которые я написал :
Цепи ваши сеттеры
Если вы инициализируете или сбрасываете несколько значений, объедините их во все переменные, которые в нем нуждаются:
Неявное кастинг
Не проверяйте свои типы, просто используйте их как есть.
parseInt()
стоит10
персонажей. Если вам нужно изгнать из строки, будьте изобретательны:Избегайте точек с запятой
JavaScript имеет автоматическую вставку точек с запятой. Используйте это часто и хорошо.
Однострочники
Сохраните в скобках, запихивая как можно больше в отдельные строки или параметры:
Операторы приращения / убывания
а также
может быть легко переписан как
а также
соответственно.
Использовать
this
илиself
вместоwindow
в глобальном контекстеСамо собой разумеющееся 2 символа сбережений.
Используйте скобочные обозначения для повторного доступа к свойствам
Это определенно баланс между длиной имени свойства и количеством обращений. Вместо того, чтобы
a.longFunctionName()
дважды вызывать с точечной нотацией, короче сохранить имя и вызвать функцию через скобочную нотацию:vs-
это особенно эффективно с такими функциями,
document.getElementById
которые можно уменьшить доd[e]
.Примечание:
В скобках обозначены
6 + name.length
символы в первый раз. Каждый последующий доступ имеет стоимость3
символов.Для точечной нотации все обращения стоят
name.length + 1
(+1 для.
) символов.Используйте этот метод, если
6 + name.length + (3 * (accesses - 1)) < accesses * (name.length + 1)
.len = длина имени свойства
i = минимальный доступ для использования
Количество доступов также может охватывать несколько объектов. Если вы используете
.length
4 или более раз для разных массивов, вы можете использовать одну и ту же переменную, содержащую строку'length'
.источник
c = ~~a-~~b
должно бытьc = ~~a+~~b
. Кроме того, вы можете неявно приводить к целому числу|0
, например, используяMath.random()*6|0
.a
иb
являются строками, вы можете сделать,+a+b
чтобы преобразовать в число и добавить их.d- -b
в своем коде когда-нибудь ...a.f=a.longfunctionname;a.f(b);a.f(c);a.f(d)
Разделение по номерам для сохранения кавычек:
источник
.split`...`
"alpha,bravo,charlie".split`,`
Используйте оператор запятой, чтобы избежать скобок (также относится к C ):
Вместо
который на один символ длиннее.
источник
Короче генерация случайных чисел
Если вам нужен случайный логический (
0
или1
):Если вам нужно случайное целое число
0 <= n < 1337
:Это работает, потому что a
Date
хранится внутри JavaScript в виде количества миллисекунд с начала эпохи, поэтому наnew Date
него навязывают,123somebignumber456
когда вы пытаетесь выполнить с ним целочисленную математику.Конечно, эти «случайные» числа на самом деле не будут такими случайными, особенно если вы вызываете их несколько раз подряд, так что имейте это в виду.
источник
Вы можете использовать объектную буквальную форму get / set, чтобы избежать использования ключевого слова
function
.источник
Это менее известный и менее используемый, но может быть впечатляющим, если используется в правильной ситуации. Рассмотрим функцию, которая не принимает аргументов и всегда возвращает другое число при вызове, и возвращенное число будет использовано в вычислении:
Обычно вы можете сократить эту функцию, используя однобуквенное имя переменной:
Лучший способ уменьшить длину - злоупотреблять
valueOf
, что дает вам экономию 2 символов за вызов. Полезно, если вы вызываете функцию более 5 раз:источник
let a=[5,6,7,8,9,10,11,12].map(x=>x*Math.random()|0)
илиlet a=Array(7).map((_,i)=>i*Math.random()|0+5)
36 или 42 байта, соответственно.r()
или сделать его короче?r={valueOf:Math.random}
Это просто гений: DИспользование преимуществ операторов короткого замыкания
Вместо длинных
if
операторов или использования троичных операторов вы можете использовать&&
и||
сократить свой код. Например:может стать
||
Оператор часто используется таким образом , для установки по умолчанию:Это так же, как написание
Создание повторяющихся строк с использованием массива
Если вы хотите инициализировать длинную строку определенного символа, вы можете сделать это, создав массив длиной n + 1 , где n - количество повторений символа:
Чем больше строка, тем больше экономия.
Разбор чисел
Используйте
+
и~
операторы вместоparseFloat()
илиparseInt()
при объединении строкового типа, который является просто числом, к числовому типу:Будьте осторожны, другие типы могут объединяться с этими операторами (например,
true
стать1
) пустой строкой или строкой, содержащей только пробел0
. Это может быть полезно в определенных обстоятельствах, однако.источник
str.repeat(count)
Вставить инициализацию переменной в вызов prompt () для получения пользовательского ввода
Вместо того, чтобы использовать
Как побочный эффект, он отображает входное значение в окне подсказки, сохраняя при этом 1 символ.
источник
[1,2,3].join('',i=5)
в случаях, когда она сохраняет пару фигурных скобок.i=5,[1,2,3].join()
.Объединить вложенные в петли:
Пример с разными значениями для
i
/j
:источник
i*j
и операторы деления / модуля извлекают отдельные значенияi
иj
.Юникод ярлыки
Если вы используете чертовски встроенную собственность на большом соревновании по гольфу, вы можете присвоить псевдониму каждую собственность эквиваленту одного символа:
После выполнения кода выше вы можете использовать его следующим образом:
"foo".Č(/.*/,'bar') // replaces foo with bar
Это стоит 118 байт, поэтому в некоторых ситуациях это может оказаться бесполезным.
Это может зависеть от браузера, и я не уверен, что он короче
with(Array){join(foo),...}
или определяет переменные как используемые свойства,with(Array){j=join,m=map...}
но все же стоит упомянуть.источник
Math
потому что у него нет.prototype
атрибута. Однако, удаливMath
, мне удалось воспроизвести это до 114-байтового фрагмента, который назначает их всем однобайтовым буквам. Вы можете найти это здесь .À
-ÿ
, который еще один байт каждый в ISO-8859-1 кодирования (который поддерживает JS). В Firefox 50 это, к сожалению, включает.localeCompare
метод×
, но обычно это не должно быть проблемой. источникПреобразование
while
цикла вfor
цикл часто эквивалентно:Но вторая форма может иметь объединенную инициализацию переменной:
Обратите внимание, что вторая форма на один символ короче первой.
источник
Исключение злоупотребляет
если строковые / символьные литералы запрещены, вы можете использовать блок try catch:
теперь
str
равняется"something"
если нужно больше строк, вы можете связать их числом (например, нулями)
теперь
arr
равняется["something", "foo", "bar", " is not defined"]
источник
Если вы инициализируете переменную
1
в каждой итерации цикла (например, сбрасываете переменную во внешнем цикле для внутреннего цикла), как показано ниже (из моего ответа на этот вопрос ):Поскольку результатом условия like
j++<=n
является1
всякий раз, когда оно имеет значение true, вы можете просто назначить условие непосредственно переменной (поскольку, когда оно становится ложным, цикл прекращает выполнение и больше не имеет значения):Обычно вы можете сохранить 2 символа, используя этот метод. С уважением к
@ugoren
идее в комментариях к этому ответу.В качестве другого примера я также применил этот трюк к своему ответу здесь с выражением
w=r=++c<S.length
во внешнем цикле for, сохранив всего 4 символа.источник
Если вы можете принять специальные сценарии Spidermonkey (на данный момент), вы можете использовать функции стрелок ECMAScript 6 . Вместо написания кода, как показано ниже.
Вы можете сократить это, как это.
источник
Если вам нужно проверить NaN, не используйте
isNaN(x)
, но используйтеx!=x
, который короче и также работает.Обратите внимание, что это работает только если
typeof(x) === "number"
; если это строка, например,isNaN("string")
возвращаетtrue
, но"string" != "string"
возвращаетfalse
. Спасибо Cyoce за указание на это!источник
isNaN("string")
возвращаетсяtrue
, тогда как"string"!="string"
возвращаетсяfalse
(очевидно)if(!x){
, если вы обнаруживаетеNaN
явно.x
к числу,+x!=+x
делает его эквивалентнымisNaN(x)
, но все же на 2 символа короче. Затем+"string"!=+"string"
возвращает истину.Сумма массива / продукт / частное
ES5 : 17 байт
ES6 : 15 байт
Конечно, вы можете поменять их
+
на что угодно, например,*
на продукт или/
частное.источник
Используйте побитовую операцию, чтобы округлить число до нуля:
(Источник: Случайная игра в кости )
Приоритет оператора определяет, что будет короче в вашей программе.
источник
n=prompt()|0
.Math.floor
ужасно медленная .. почти не следует использовать, я бы сказал.Looping Tip I
Вы можете сохранить
1
символ при зацикливании, изменивi
на последний использованный:Примечание: работает
--
также (но измените цикл соответственно, чтобы избежать бесконечного цикла)Looping Tip II
Есть определенные сценарии, в которых вы можете сохранить один символ, играя с инкрементным оператором и значениями:
Примечание: нужно обратить внимание, когда, например
0 to -1
. и9 to 10, 99 to 100
, так что поиграйте, пока не найдете способ сохранить персонажаисточник
Использовать
^
вместо!=
или==
при сравнении с целым числомЗамените вызовы встроенных математических функций более короткими выражениями.
источник
-
вместо!=
целых чисел; Например,n!=1?a:b
будет эквивалентноn-1?a:b
Стоит отметить, что в некоторых случаях вы можете использовать строку вместо нуля, чтобы сохранить несколько байтов здесь и там в циклах:
источник
Очень простой, даже так, никто не упомянул об этом.
Если вы используете
Math.min()
илиMath.max()
можете сохранить 6 символов, сделав это:источник
округление
Я знаю, что альтернативы
Math.floor()
были опубликованы, но как насчет других?Напольное покрытие:
Округление:
Потолок:
источник
0|x+1
просто добавляется 1, если число, которое вы хотите найти, уже является целым числом. (В основном) безопасная альтернатива есть0|x+1-1e9
, но она всего на три байта короче.0|x+1-1e-9
?x%1?-~x:x
(9 символов) - лучшая альтернатива. Однако, как альтернативы настила0|x
и~~x
, это работает только для положительных чисел.В тех случаях, когда вы используете троичный оператор для выбора между двумя числами , а условным условием является либо логическое значение, либо число
1 or 0
, вы можете вместо этого выполнять математические операции:Примечание: В дополнение к этому, вам нужно будет удалить ненужные
0-
,+0
, и+-
т.д.Примечание 2: есть единичный случай, когда
(x) !== (x?1:0)
, как этоx
должно быть,typeof === "number"
для его работы. Однако в случае с(-x)
этим все работает просто отлично.Примечание 3: Если вы не нашли сбережения, просто используйте первый
(x?y:z)
Ранее я думал, что метод B никогда не сможет победить A, однако существуют исключения:
Я создал проект GitHub, который делает упрощение для нас ( демонстрация jsFiddle )
источник
void 0
(это не функция, а ключевое слово) не является значением, оно просто возвращаетundefined
.a
для его работы должно быть либо 1, либо 0tl; dr: использовать функции ES6!
Функции стрелок
Документ: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/arrow_functions
Пример:
источник
for
..of
это круто. Даже корочеfor each
..in
.b = [s(x) for (x of a)]
.Злоупотреблять литералами
Недавний пример: проверьте,
"c"
есть ли прописные или строчные буквы, не имеет значения, если не букваисточник
String({})
дает"[object Object]"
.Как сравнить число с помощью того, как числа превращаются в логические значения:
Если вы собираетесь проверить , если что - то равно положительное число , вы можете вычесть эту сумму и обратную , что было внутри
if
иelse
блоков:И в случае, если вы хотите сравнить с отрицательным числом (* отличным от
-1
), вам просто нужно добавить это число вместо вычитания.* ну, вы, конечно, можете использовать
x.indexOf(y) + 1
, но в особом случае у-1
вас есть возможность использовать~x.indexOf(y)
вместо этого.источник
Используйте нестандартную функцию «закрытия выражений» в Mozilla, чтобы сохранить множество символов в скрипте, который должен работать только в движках SpiderMonkey / Firefox или Rhino. Например,
становится
См. Страницу переполнения стека для большего количества таких уловок.
источник
->bar
let foo = () => bar;
иронически короче, чем приведенный выше код для игры в гольф.foo=_=>bar
еще короче.Используйте
if(~a.indexOf(b))
вместоif(a.indexOf(b)!=-1)
источник
Вместо написания
true
вы можете использовать!0
.источник
!1
дляfalse
.1
дляtrue
и0
дляfalse
, если вам действительно не нужны буквальные значения.Преобразование в логическое значение :
Примечание: Это изменение
0
,""
,false
,null
,undefined
иNaN
кfalse
(все остальноеtrue
)источник