Это похоже на другие «Советы по игре в гольф в <...>», но специально нацелено на новые функции в JavaScript, появившиеся в ECMAScript 6 и выше.
JavaScript по своей сути является очень многословным язык, function(){}
, .forEach()
, преобразование строки в массив, массив типа объекта в массив, и т.д., и т.д., супер раздувается и не здоровые для игры в гольф.
ES6 +, с другой стороны, имеет некоторые удобные функции и уменьшенную площадь. x=>y
, [...x]
И т.д. лишь некоторые из примеров.
Пожалуйста, опубликуйте несколько полезных трюков, которые помогут избавиться от этих нескольких лишних байтов из вашего кода.
ПРИМЕЧАНИЕ: трюки для ES5 уже доступны в разделе Советы по игре в гольф на JavaScript ; ответы на эту тему должны быть сосредоточены на уловках, доступных только в ES6 и других будущих версиях ES.
Тем не менее, эта тема также для пользователей, которые в настоящее время играют в гольф, используя функции ES5. Ответы могут также содержать советы, которые помогут им понять и сопоставить функции ES6 с их стилем кодирования ES5.
источник
Трюки узнали здесь, так как я присоединился
Мой основной язык программирования - JS и в основном ES6. С тех пор, как я присоединился к этому сайту неделю назад, я научился многим полезным трюкам от других участников. Я объединяю некоторые из них здесь. Все кредиты сообществу.
Функции стрелок и петли
Все мы знаем, что функции стрелок экономят много байтов
Но вы должны иметь в виду несколько вещей
,
то есть(a=b,a.map(d))
- Здесь возвращаемое значение является последним выражениемa.map(d)
do something
часть состоит из более чем одного утверждения, то вам нужно добавить окружающие{}
скобки.{}
скобки, вам нужно добавить явный оператор возврата.Вышеприведенное справедливо много раз, когда задействованы циклы. Так что-то вроде:
Здесь я трачу как минимум 9 символов из-за возврата. Это может быть оптимизировано.
.map
или.every
или.some
вместо. Обратите внимание, что если вы хотите изменить тот же массив, который вы отображаете, он потерпит неудачу.Таким образом, выше становится:
удаленные символы:
{}return
добавленные персонажи:
(){}>|
Обратите внимание, как я вызываю метод замыкания, который правильно заполняет переменную,
n
а затем, поскольку метод замыкания ничего не возвращает (т. Е. Возвращаетundefined
), я бита или его и возвращаю массивn
все в одном выражении внешней функции стрелкиu
Запятые и точки с запятой
Избегайте их, что бы ни случилось,
Если вы объявляете переменные в цикле или как уже упоминалось в предыдущем разделе, используя
,
отдельные операторы, чтобы иметь функции стрелок с одним оператором, то вы можете использовать несколько довольно изящных приемов, чтобы избежать их,
или;
сбрить последние несколько байтов.Рассмотрим этот код:
Здесь я вызываю много методов для инициализации многих переменных. Каждая инициализация использует
,
или;
. Это может быть переписано как:Обратите внимание, как я использую тот факт, что метод не беспокоит передаваемую ему переменную, и использую этот факт, чтобы сбрить 3 байта.
Разное
.search
вместо.indexOf
Оба дают одинаковый результат, но
search
короче. Хотя поиск ожидает регулярное выражение, поэтому используйте его с умом.`Строки шаблона`
Это очень удобно, когда вам нужно объединить одну или несколько струнных частей на основе определенных условий.
Возьмите следующий пример для вывода квин в JS
против
В строке шаблона, которая является строкой внутри двух обратных кавычек (`), все, что внутри a
${ }
, обрабатывается как код и оценивается для вставки полученного ответа в строку.Я опубликую еще несколько трюков позже. Удачного игры в гольф!
источник
regexp
не строка. Попробуйте'abc'.search('.')
.map
, рекурсия - это еще один метод, который иногда может помочь вам превратитьfor
цикл в выражение.Использование сокращений свойств
Сокращения свойств позволяют устанавливать переменные для значений массивов:
Это также может быть использовано как:
Вы даже можете использовать это для обращения переменных:
Вы также можете использовать это для сокращения
slice()
функций.Базовые преобразования
ES6 предоставляет гораздо более короткий способ преобразования форм Base-2 (двоичный) и Base-8 (восьмеричный) в десятичный:
+
может использоваться для преобразования двоичной, восьмеричной или шестнадцатеричной строки в десятичное число. Вы можете использовать0b
,0o
и0x
, для двоичного, восьмеричного и шестнадцатеричного соответственно:Если вы используете это> 7 раз, то использовать
parseInt
и переименовать его будет короче :Теперь
p
можно использовать дляparseInt
экономии многих байтов в долгосрочной перспективе.источник
'0x'+v-0
еще короче, но может не работать так же хорошо в некоторых сценариях.0767
(ES5) короче, чем0o767
(ES6) обозначения.0767
- это нестандартное расширение, и оно строго запрещено в строгом режиме.0
восьмеричные литералы с префиксом никуда не денутся и так же корректны, как и экмаскрипт0o
.Использование строковых шаблонов с функциями
Когда у вас есть функция с одной строкой в качестве аргументов. Вы можете опустить,
()
если у вас нет выражений:источник
fun`string`
так же, какfun(["string"])
нетfun("string")
. Это хорошо для функций, которые преобразуются в строку, напримерalert
, но для других это может вызвать проблемы. Для получения дополнительной информации см. Статью MDNfun`foo${1}bar${2}baz
эквивалентноfun(["foo","bar","baz"],1,2)
Массивы (Firefox 30-57)
Примечание: понимание массива никогда не было стандартизировано и устарело в Firefox 58. Используйте на свой страх и риск.
Первоначально спецификация ECMAScript 7 содержала множество новых функций на основе массива. Хотя большинство из них не вошли в финальную версию, поддержка Firefox (ed), возможно, самая большая из этих функций: новый модный синтаксис, который можно заменить,
.filter
и.map
сfor(a of b)
синтаксисом. Вот пример:Как видите, две строки не так уж отличаются, кроме второй, не содержащей громоздких ключевых слов и функций стрелок. Но это только объясняет порядок
.filter().map()
; что произойдет, если у вас есть.map().filter()
вместо этого? Это действительно зависит от ситуации:Или что, если ты хочешь или
.map
или.filter
? Ну, обычно получается меньше, хорошоТак что мой совет использовать постижения массива , где вы обычно используете
.map
и.filter
, но не только один или другие.Строковые Понимания
Хорошая вещь в понимании ES7 состоит в том, что, в отличие от функций, специфичных для массива, таких как
.map
и.filter
, они могут использоваться с любым итерируемым объектом, а не только с массивами. Это особенно полезно при работе со строками. Например, если вы хотите запустить каждый символc
в строке черезc.charCodeAt()
:Это два байта, сохраненные в довольно небольшом масштабе. А что если вы хотите отфильтровать определенные символы в строке? Например, этот хранит только заглавные буквы:
Хм, это не короче. Но если мы объединим два:
Вау, целые 10 байтов сохранены!
Еще одним преимуществом понимания строк является то, что жестко закодированные строки сохраняют дополнительный байт, так как вы можете опустить пробел после
of
:индексирование
Понимание массива затрудняет получение текущего индекса в строке / массиве, но это можно сделать:
Главное, о чем следует помнить, это убедиться, что индекс увеличивается каждый раз, а не только при выполнении условия.
Генератор понимания
Генераторные понимания имеют в основном тот же синтаксис, что и массивы; просто замените скобки на круглые скобки:
Это создает генератор, который работает почти так же, как массив, но это история для другого ответа.
Резюме
В принципе, хотя понимание обычно короче
.map().filter()
, все сводится к специфике ситуации. Лучше всего попробовать оба способа и посмотреть, что получится лучше.PS Не стесняйтесь предложить другой связанный с пониманием совет или способ улучшить этот ответ!
источник
(x,y)=>[...Array(y-x)].map(a=>x++)
x=>[...Array(x).keys()]
n=>[for(x of Array(n).keys())if(/1/.test(x))x]
(сохраняет 7 байтов)Выражения функций в ES6 используют обозначение стрелки, и это помогает значительно экономить байты по сравнению с версией ES5:
Если ваша функция имеет только один параметр, вы можете опустить скобки, чтобы сохранить два байта:
Если ваша функция вообще не имеет параметров, объявите ее так, как если бы она имела один для сохранения одного байта:
Осторожно: функции стрелок не совсем такие, как
function () {}
. Правилаthis
разные (и лучше ИМО). См документыисточник
this
и т. Д.f=(...x)=>x
иметь ееf(1,2,3) => [1,2,3]
.(x,y)=>...
вы можете сохранить байт с каррированием , заменив его наx=>y=>...
Использование
eval
для функций со стрелками с несколькими операторами иreturn
Один из самых нелепых трюков, с которыми я столкнулся ...
Представьте себе простую функцию со стрелкой, которая требует нескольких операторов и a
return
.Простая функция, принимающая один параметр
a
, который перебирает все целые числа[0, a)
и прикрепляет их к концу выходной строкиo
, которая возвращается. Например, вызов этого4
параметра в качестве параметра даст результат0123
.Обратите внимание, что эта функция стрелки должна быть заключена в фигурные скобки
{}
, и иметьreturn o
в конце.Эта первая попытка весит 39 байт .
Неплохо, но с помощью
eval
мы можем улучшить это.Эта функция удалила фигурные скобки и оператор return, обернув код в
eval
и просто сделав последний оператор вeval
оценке too
. Это приводитeval
к возвратуo
, что, в свою очередь, приводит к возврату функцииo
, так как теперь это один оператор.Эта улучшенная попытка весит 38 байтов , сохраняя один байт от оригинала.
Но подождите, это еще не все! Eval-операторы возвращают все, что их последний оператор оценил. В этом случае
o+=i
оцениваетo
, поэтому нам не нужно;o
! (Спасибо, edc65!)Эта последняя попытка весит всего 36 байтов - 3 байта экономии по сравнению с оригиналом!
Этот метод может быть распространен на любой общий случай, когда функция со стрелкой должна возвращать значение и иметь несколько операторов (которые не могут быть объединены другими средствами)
становится
сохранение байта.
Если
statement2
оцениватьv
, это может бытьсохраняя в общей сложности 3 байта.
источник
;o
- попробуйте:a=>eval('for(o="",i=0;i<a;i++)o+=i')
Предпочитать строки шаблона новые строки над "\ n"
Это начнет окупаться даже при появлении одного символа новой строки в вашем коде. Один вариант использования может быть:
(16 байт)
(15 байт)
Обновление: Вы можете даже оставить фигурные скобки из-за помеченных строк шаблона (спасибо, edc65!):
(13 байт)
источник
Заполнение массивов - статические значения и динамические диапазоны
Первоначально я оставил их в качестве комментариев при понимании, но так как этот пост был в основном сфокусирован на понимании, я подумал, что было бы хорошо дать этому свое место.
ES6 дал нам возможность заполнять массивы статическими значениями без использования циклов:
Оба возвращают массив длины x, заполненный значением 0.
Если вы хотите заполнить массивы динамическими значениями (например, диапазон от 0 до x), результат будет немного длиннее (хотя все еще короче, чем старый):
Оба возвращают массив длины x, начиная со значения 0 и заканчивая x-1.
Причина, по которой вам нужно,
.fill()
заключается в том, что простая инициализация массива не позволит вам отобразить его. То есть выполнениеx=>Array(x).map((a,i)=>i)
вернет пустой массив. Вы также можете обойти необходимость заполнения (и, следовательно, сделать его еще короче), используя оператор распространения, например, так:Используя оператор и
.keys()
функцию распространения, теперь вы можете сделать короткий диапазон 0 ... x:Если вам нужен пользовательский диапазон от x ... y или специальный диапазон (например, четные числа), вы можете избавиться от него
.keys()
и просто использовать.map()
или использовать.filter()
с помощью оператора распространения:источник
x=>Array(x).fill(i=0).map(a=>i++)
Кроме того, я не уверен, что 0 в.fill(0)
необходим. Вы пробовали это без?a=>a%2-1
работает нормально, как иa=>a%2<1
.[...Array(x)]
работает так же хорошоArray(x).fill()
, и на 2 байта короче.x=>[...Array(x)].map((a,i)=>i)
1/4
пример будет написан короче[0,0,0,0]
, и 2) строковые функции зависят от реализации, поэтому не будут возвращать надежную длину (Map
32 байта в Chrome, но 36 байтов в Firefox).Возвращение значений в функциях со стрелками
Общеизвестно, что если после объявления функции arrow один оператор возвращает результат этого оператора:
-7 байт
Поэтому, когда это возможно, объедините несколько утверждений в одно. Это проще всего сделать, заключив операторы в круглые скобки и разделив их запятыми:
-8 байт
Но если есть только два утверждения, обычно возможно (и короче) объединить их с
&&
или||
:-9 байт
Наконец, если вы используете карту (или аналогичную) и вам нужно вернуть число, и вы можете гарантировать, что карта никогда не вернет массив длиной 1 с числом, вы можете вернуть число с помощью
|
:источник
Случайные взломы шаблонов
Эта функция перезаписывает две строки (т.е. превращается
"abc","de"
в"adbec"
):Обратите внимание, что это работает только тогда, когда
x
больше, чемy
. Вы спрашиваете, как это работает?String.raw
предназначен для шаблона тега, вот так:Это в основном называет
String.raw(["x: ", "\ny: ", "\nx + y: ", ""], x, y, x + y)
, хотя это не так просто. Массив шаблона также имеет специальноеraw
свойство, которое в основном является копией массива, но с необработанными строками.String.raw(x, ...args)
в основном возвращаетсяx.raw[0] + args[0] + x.raw[1] + args[1] + x.raw[2] + ...
и так до тех пор, пока неx
кончится товар.Итак, теперь, когда мы знаем, как
String.raw
работает, мы можем использовать это в наших интересах:Конечно, для последнего,
f=(x,y)=>x.split``.join(y)
это намного короче, но вы поняли идею.Вот пара функций риффлинга, которые также работают, если
x
иy
имеют одинаковую длину:Вы можете узнать больше о
String.raw
MDN .источник
Как играть в гольф с рекурсией
Рекурсия, хотя и не самый быстрый вариант, очень часто самый короткий. Как правило, рекурсия является самой короткой, если решение может быть упрощено до решения для меньшей части задачи, особенно если ввод представляет собой число или строку. Например, если
f("abcd")
можно рассчитать из"a"
иf("bcd")
, обычно лучше использовать рекурсию.Взять, к примеру, факториал:
В этом примере рекурсия явно короче любого другого варианта.
Как насчет суммы кодов:
Это сложнее, но мы видим, что при правильной реализации рекурсия экономит 4 байта
.map
.Теперь давайте посмотрим на различные типы рекурсии:
Pre-рекурсия
Обычно это самый короткий тип рекурсии. Ввод разделен на две части
a
иb
, и функция вычисляет что-то с помощьюa
иf(b)
. Возвращаясь к нашему факториальному примеру:В этом случае,
a
это п ,b
является п-1 , а возвращаемое значениеa*f(b)
.Важное примечание: у всех рекурсивных функций должен быть способ остановить рекурсию, когда входной сигнал достаточно мал. В факториальной функции это управляется с помощью
n? :1
, т. Е. Если вход равен 0 , вернуть 1 безf
повторного вызова .Сообщение рекурсии
Пострекурсия похожа на предрекурсию, но немного отличается. Ввод делится на две части
a
иb
, и функция вычисляет что-то с помощьюa
, а затем вызываетf(b,a)
. Второй аргумент обычно имеет значение по умолчанию (т.е.f(a,b=1)
).Предварительная рекурсия хороша, когда вам нужно сделать что-то особенное с конечным результатом. Например, если вы хотите факториал числа плюс 1:
Однако даже в этом случае post- не всегда короче, чем использование предварительной рекурсии в другой функции:
Так, когда это короче? Вы можете заметить, что пострекурсия в этом примере требует скобок вокруг аргументов функции, в то время как предварительная рекурсия этого не делает. Как правило, если оба решения нуждаются в круглых скобках вокруг аргументов, пострекурсия будет примерно на 2 байта короче:
(программы здесь взяты из этого ответа )
Как найти кратчайшее решение
Обычно единственный способ найти самый короткий метод - это попробовать все из них. Это включает в себя:
.map
(для строк, либо[...s].map
илиs.replace
, для чисел, вы можете создать диапазон )И это только самые распространенные решения; лучшее решение может быть их комбинацией или даже чем-то совершенно другим . Лучший способ найти самое короткое решение - попробовать все .
источник
Более короткие способы сделать
.replace
Если вы хотите заменить все экземпляры одной точной подстроки на другой в строке, очевидным способом будет:
Тем не менее, вы можете сделать на 1 байт короче:
Обратите внимание, что это больше не короче, если вы хотите использовать какие-либо функции регулярных выражений, кроме
g
флага. Однако, если вы заменяете все экземпляры переменной, она обычно намного короче:Иногда вы захотите отобразить каждый символ в строке, заменив каждый чем-то другим. Я часто ловлю себя на этом:
Однако
.replace
почти всегда корочеТеперь, если вы хотите отобразить каждый символ в строке, но не заботитесь о результирующей строке,
.map
обычно лучше, потому что вы можете избавиться от.join``
:источник
/\w/g
заинтересованы только определенные символы, соответствующие регулярному выражению (например ), использование замены будет намного лучше, чем в этой демонстрации .Написание литералов RegEx с
eval
Конструктор регулярных выражений может быть очень громоздким из-за его длинного имени. Вместо этого напишите литерал с eval и обратными галочками:
Если переменная
i
равнаfoo
, это сгенерирует:Это равно:
Вы также можете использовать,
String.raw
чтобы избежать необходимости повторять обратную косую черту\
Это выведет:
Что равно:
Иметь ввиду!
String.raw
занимает много байтов, и если у вас есть по крайней мере девять обратных слэшей,String.raw
будет больше.источник
new
, поэтому использование конструктора на самом деле короче для второго примера.forEach
противfor
петельВсегда предпочитаю
.map
любой цикл. Простая, мгновенная экономия.источник
Использование неинициализированных счетчиков в рекурсии
Примечание . Строго говоря, это не относится к ES6. Однако более разумно использовать и злоупотреблять рекурсией в ES6 из-за краткого характера функций стрелок.
Довольно часто встречается рекурсивная функция, которая использует счетчик,
k
изначально установленный в ноль и увеличивающийся на каждой итерации:При определенных обстоятельствах можно пропустить инициализацию такого счетчика и заменить
k+1
на-~k
:Этот трюк обычно экономит 2 байта .
Почему и когда это работает?
Формула , которая позволяет это
~undefined === -1
. Итак, на первой итерации,-~k
будет оцениваться до1
. На следующих итерациях,-~k
по существу, эквивалентно тому,-(-k-1)
что равноk+1
, по крайней мере, для целых чисел в диапазоне [0… 2 31 -1].Однако вы должны убедиться, что
k = undefined
выполнение первой итерации не нарушит поведение функции. Вы должны особенно помнить, что большинство арифметических операций, связанныхundefined
сNaN
.Пример № 1
Учитывая положительное целое число
n
, эта функция ищет наименьшее целое число,k
которое не делитсяn
:Его можно сократить до:
Это работает , потому что
n % undefined
этоNaN
, что falsy. Это ожидаемый результат на первой итерации.[Ссылка на оригинальный ответ]
Пример № 2
Учитывая положительное целое число
n
, эта функция ищет целое числоp
такое, что(3**p) - 1 == n
:Его можно сократить до:
Это работает, потому что
p
не используется вообще на первой итерации (n<k
будучи ложным).[Ссылка на оригинальный ответ]
источник
ES6 функции
математический
Math.cbrt(x)
сохраняет символы, чемMath.pow(x,1/3)
.3 символа сохранены
Math.hypot(...args)
полезно, когда вам нужен квадратный корень из суммы квадратов аргов. Заставить код ES5 сделать это гораздо сложнее, чем использовать встроенный.Функция
Math.trunc(x)
не будет полезна, так какx|0
она короче. (Спасибо Mwr247!)Есть много свойств, которые требуют много кода для ES5, но проще в ES6:
Math.acosh
,asinh
,atanh
,cosh
,sinh
,tanh
. Вычисляет гиперболический эквивалент тригонометрических функций.Math.clz32
, Возможно, это можно сделать в ES5, но теперь это стало проще. Считает лидирующие нули в 32-битном представлении числа.Есть намного больше, так что я просто буду перечислять некоторые из них :
Math.sign
,Math.fround
,Math.imul
,Math.log10
,Math.log2
,Math.log1p
.источник
Math.trunc(x)
в четыре раза длиннееx|0
.Math.hypot(a,b) => Math.sqrt(a*a+b*b)
(на 3 байта длиннее; с большим количеством аргументов становится еще длиннее),Math.sign(a) => (a>0)-(a<0)
(короче на 1 байт, но в некоторых случаях требуются круглые скобки; может не работатьNaN
)Оптимизация небольших постоянных диапазонов для
map()
контекст
map()
for
может быть заменен либо:
или чаще:
Array(N)
NB . Длина кода обратного вызова
F(i)
не учитывается.Оптимизации без счетчика
NB . Длина кода обратного вызова
F()
не учитывается.источник
2**26
быть2**29
?.keys()
, вам не нужна лямбда:[...Array(10).keys()].map(do_something_with)
Разрушающие задания
ES6 вводит новый синтаксис для деструктурирующих назначений, то есть разделение значения на части и назначение каждого фрагмента другой переменной. Вот несколько примеров:
Строки и массивы
Объекты
Эти назначения также могут использоваться в параметрах функции:
источник
Еще один способ избежать
return
Вы знаете, что вы должны использовать eval для функций со стрелками с несколькими операторами и возвратом . В некоторых необычных случаях вы можете сэкономить больше, используя внутреннюю подфункцию.
Я говорю необычно, потому что
Возвращаемый результат не должен быть последним выражением, вычисленным в цикле
Должно быть (как минимум) 2 разных инициализации перед циклом
В этом случае вы можете использовать внутреннюю подфункцию без возврата, передав одно из начальных значений в качестве параметра.
пример Найти обратную сумму суммы функции exp для значений в диапазоне от a до b.
Долгий путь - 55 байт
С eval - 54 байта
С внутренней функцией - 53 байта
Обратите внимание, что без требования нижнего предела диапазона
a
я могу объединить инициализации i и r, и версия eval будет короче.источник
a
(i,b)=>{for(r=0;i<=b;i++)r+=Math.exp(i);return 1/r}
return a/r
лучший пример(a,b)=>1/eval("for(r=0,i=a;i<=b;i++)r+=Math.exp(i)")
и в этом случае(i,b)=>1/eval("for(r=0;i<=b;)r+=Math.exp(i++)")
Использование синтаксиса каррирования для двоичных и рекурсивных функций
Диадические функции
Всякий раз, когда функция принимает ровно два аргумента без значений по умолчанию, использование синтаксиса каррирования сохраняет один байт.
До
Вызывается с
f(a,b)
После
Вызывается с
f(a)(b)
Примечание : этот пост в Meta подтверждает правильность этого синтаксиса.
Рекурсивные функции
Использование синтаксиса каррирования может также сэкономить несколько байтов, когда рекурсивная функция принимает несколько аргументов, но ей нужно только обновить некоторые из них между каждой итерацией.
пример
Следующая функция вычисляет сумму всех целых чисел в диапазоне
[a,b]
:Поскольку
a
остается неизменным в течение всего процесса, мы можем сохранить 3 байта, используя:Примечание . Как заметил Нейл в комментариях, тот факт, что аргумент явно не передается рекурсивной функции, не означает, что его следует считать неизменным. При необходимости, можно изменить
a
в коде функции сa++
,a--
или любой другой аналогичный синтаксис.источник
a=>F=b=>a>b?0:a+++F(b)
, модифицируяa
для каждого рекурсивного вызова. Это не поможет в этом случае, но может сохранить байты в случаях с большим количеством аргументов.Функция тестирования на первичность
Следующая 28-байтовая функция возвращает
true
простые числа иfalse
не простые числа:Это можно легко изменить, чтобы рассчитать другие вещи. Например, эта 39-байтовая функция считает количество простых чисел, меньших или равных числу:
Если у вас уже есть переменная
n
которую вы хотите проверить на простоту, функцию простоты можно немного упростить:Как это устроено
Примечание. Это приведет к ошибке «ошибка слишком большой рекурсии» при вызове с достаточно большим вводом, например 12345. Вы можете обойти это с помощью цикла:
источник
x==1
может быть,x<2
для экономии.1
или0
(потомуx
что будет0
или-1
, соответственно)!~-x
за -0 байт.Array#concat()
и оператор распространенияЭто во многом зависит от ситуации.
Объединение нескольких массивов.
Предпочитаю функцию concat, кроме клонирования.
0 байт сохранено
3 байта потрачено впустую
3 байта сохранены
6 байтов сохранено
Предпочитаю использовать уже существующий массив
Array#concat()
.Простые 4 байта сохранены
источник
Вернуть промежуточный результат
Вы знаете, что с помощью оператора запятой вы можете выполнить последовательность выражений, возвращающих последнее значение. Но злоупотребляя синтаксисом литерального массива, вы можете вернуть любое промежуточное значение. Это полезно, например, в .map ().
источник
.join('')
может быть.join``
Установить параметры функции по умолчанию
Это действительно полезно ...
Тем не менее, следует понимать, что что-то вроде этого
_=>_||'asdf'
короче, когда вы передаете только один (полезный) аргумент функции.источник
_=>_||'asdf'
в большинстве случаев использование OR обычно короче"asdf"
для ввода""
(пустая строка).undefined
, даже если вы явно передаете это значение. Например,[...Array(n)].map((a,b,c)=>b)
всегда проходитundefined
дляa
, и поэтому вы можете указать для него значение по умолчанию (хотя и не в терминахb
).использование
eval
вместо фигурных скобок для функций стрелокФункции стрелки потрясающие. Они принимают форму
x=>y
, гдеx
аргумент иy
возвращаемое значение. Тем не менее, если вам нужно использовать управляющую структуру, напримерwhile
, вам придется поставить фигурные скобки, например=>{while(){};return}
. Тем не менее, мы можем обойти это; К счастью,eval
функция берет строку, оценивает эту строку как код JS и возвращает последнее вычисленное выражение . Например, сравните эти два:Мы можем использовать расширение этой концепции для дальнейшего сокращения нашего кода: в глазах
eval
управляющих структур также возвращают свое последнее вычисленное выражение. Например:источник
Гольф Логические операции в ES6
"GLOE (S6)"
Общая логика
Скажем, вы построили заявления
s
иt
. Посмотрите, можете ли вы использовать любую из следующих замен:(Они могут не работать, если порядок неправильный; т.е.
+
и*
имеют более низкий приоритет, чем||
и&&
делают.)Кроме того, вот несколько удобных логических выражений:
s
илиt
верно / XOR:s^t
s
иt
имеют одинаковую ценность истины:!s^t
илиs==t
Логика массива
Все члены
a
удовлетворяют условиюp
:По крайней мере один член
a
удовлетворяет условиюp
:Нет члены
a
удовлетворяют условиюp
:!a.some(p)
.Элемент
e
существует в массивеa
:Элемент
e
имеет не существует в массивеa
:источник
&&
и||
какx?y:x
иx?x:y
соответственно. Но я могу видеть, как это было бы полезно в более основанных на логике программах. Одной из проблем+
будет то, что, например,3
и-3
оба правдивы, но3+-3
это не так.-
также может работать, еслиs != t
.a.filter(t=>t==e).length==a.length
это неверно. Это должно быть!a.filter(t=>t==e).length
Сократить повторные вызовы функций
Если вы повторяли вызовы функции с длинным именем, например, манипулирование холстом:
Традиционный способ сократить это - псевдоним имени функции:
Если у вас достаточно вызовов, лучше создать функцию, которая сделает эту работу за вас:
Если большинство вызовов функции связаны друг с другом, вы можете сделать так, чтобы функция возвращала себя сама, что позволяет вам обрезать два байта каждого последующего вызова:
Пример использования: 1 , 2
источник
(l=::c.lineTo)(0,100)(100,100)(100,0)(0,0);c.stroke()
c.lineTo
он сам по себе не вернется)Оператор связывания
::
Оператор связывания может использоваться для сокращения байтов по повторяющимся функциям:
Кроме того, если вы хотите использовать функцию с другим,
this
например:источник
Избегайте запятых при хранении большого количества данных
Если у вас есть много данных (т. Е. Индексов, символов и т. Д.), Которые необходимо сохранить в массиве, лучше оставить все запятые в стороне. Это работает лучше всего, если каждый фрагмент данных имеет одинаковую длину строки, 1, очевидно, является оптимальным.
43 байта (базовый уровень)
34 байта (без запятых)
Если вы готовы изменить свой доступ массиву , вы можете уменьшить его еще больше, сохранив те же значения, например:
27 байт (те же данные, только изменяет доступ к массиву)
источник