Isso é semelhante a outras "Dicas para jogar golfe em <...>", mas direcionadas especificamente aos novos recursos do JavaScript apresentados no ECMAScript 6 e acima.
JavaScript inerentemente é uma língua muito detalhado, function(){}
, .forEach()
, convertendo string para array, array como objeto a matriz, etc, etc são super incha e não é saudável para o Golfe.
O ES6 +, por outro lado, possui alguns recursos super úteis e presença reduzida. x=>y
, [...x]
etc são apenas alguns exemplos.
Publique alguns truques legais que podem ajudar a eliminar esses poucos bytes extras do seu código.
NOTA: Os truques para o ES5 já estão disponíveis em Dicas para jogar golfe em JavaScript ; as respostas a este segmento devem se concentrar em truques disponíveis apenas no ES6 e em outras versões futuras do ES.
No entanto, esse segmento também é para usuários que atualmente jogam golfe usando os recursos do ES5. As respostas também podem conter dicas para ajudá-los a entender e mapear os recursos do ES6 de acordo com o estilo de codificação do ES5.
fonte
Truques aprendidos aqui desde que entrei
Minha principal linguagem de programação é JS e principalmente ES6. Desde que entrei neste site há uma semana, aprendi muitos truques úteis com colegas. Estou combinando alguns deles aqui. Todos os créditos para a comunidade.
Funções de seta e loops
Todos sabemos que as funções de seta economizam muitos bytes
Mas você tem que ter em mente algumas coisas
,
ie(a=b,a.map(d))
- Aqui, o valor retornado é a última expressãoa.map(d)
do something
parte for mais de uma declaração, você precisará adicionar os{}
colchetes ao redor .{}
colchetes, você precisará adicionar uma declaração de retorno explícita.O acima exposto é válido muitas vezes quando você tem loops envolvidos. Então, algo como:
Aqui estou desperdiçando pelo menos 9 caracteres devido ao retorno. Isso pode ser otimizado.
.map
ou.every
ou em.some
vez disso. Observe que se você deseja alterar a mesma matriz para a qual está mapeando, ela falhará.Portanto, o acima se torna:
caracteres removidos:
{}return
caracteres adicionados:
(){}>|
Observe como eu chamo o método de fechamento, que preenche corretamente a variável
n
e, como o método de fechamento não está retornando nada (ou seja, retornandoundefined
), eu bit a bit ou retornamos a matrizn
em uma única instrução da função de seta externau
Vírgulas e ponto e vírgula
Evite-os do que nunca,
Se você estiver declarando variáveis em um loop, ou como mencionado na seção anterior, usando
,
instruções separadas para ter funções de seta de instrução única, poderá usar alguns truques bem bacanas para evitá-las,
ou;
raspar os últimos bytes.Considere este código:
Aqui, estou chamando muitos métodos para inicializar muitas variáveis. Cada inicialização está usando um
,
ou;
. Isso pode ser reescrito como:Observe como uso o fato de o método não incomodar a variável passada a ele e o uso para depurar 3 bytes.
Diversos
.search
ao invés de.indexOf
Ambos dão o mesmo resultado, mas
search
é mais curto. Embora a pesquisa espere uma expressão regular, use-a com sabedoria.`Strings de modelo`
Isso é super útil quando você precisa concatenar uma ou mais partes da corda com base em determinadas condições.
Pegue o exemplo a seguir para gerar uma quine em JS
vs.
Em uma string de modelo, que é uma string dentro de duas aspas (`), qualquer coisa dentro de a
${ }
é tratada como um código e avaliada para inserir a resposta resultante na string.Vou postar mais alguns truques mais tarde. Feliz golfe!
fonte
regexp
, não uma string. Tente'abc'.search('.')
.map
, a recursão é outra técnica que às vezes pode ajudá-lo a transformar umfor
loop em uma expressão.Usando atalhos de propriedades
As abreviações de propriedades permitem definir variáveis para os valores de uma matriz:
Isso também pode ser usado como:
Você pode até usar isso para reverter variáveis:
Você também pode usar isso para reduzir
slice()
funções.Conversões básicas
O ES6 fornece uma maneira muito mais curta de converter o formulário Base-2 (binário) e Base-8 (octal) em decimal:
+
pode ser usado para converter uma seqüência de caracteres binária, octal ou hexadecimal em um número decimal. Você pode usar0b
,0o
e0x
, por binário, octal e hexadecimal, respectivamente .:Se você estiver usando isso> 7 vezes, será mais curto usá
parseInt
-lo e renomeá-lo:Agora
p
pode ser usadoparseInt
, economizando muitos bytes a longo prazo.fonte
'0x'+v-0
é ainda mais curto, mas pode não funcionar tão bem em alguns cenários.0767
(ES5) é mais curto que a0o767
notação (ES6).0767
é uma extensão não padrão e é explicitamente proibida no modo estrito.0
literais octais pré-prefixados não estão indo a lugar algum e são tão válidos quanto ecmascript0o
.Usando modelos de string com funções
Quando você tem uma função com uma string como argumento. Você pode omitir o
()
se você não tiver nenhuma expressão:fonte
fun`string`
é o mesmo quefun(["string"])
nãofun("string")
. Isso é bom para funções que convertem para string, comoalert
, mas para outras, isso pode causar problemas. Para obter mais informações, consulte o artigo MDNfun`foo${1}bar${2}baz
é equivalente a chamarfun(["foo","bar","baz"],1,2)
Compreensões de matriz (Firefox 30-57)
Nota: as compreensões de array nunca foram padronizadas e tornaram-se obsoletas com o Firefox 58. Use por sua própria conta e risco.
Originalmente, a especificação do ECMAScript 7 continha vários novos recursos baseados em array. Embora a maioria deles não tenha chegado à versão finalizada, o Firefox suporta (possivelmente) o maior desses recursos: nova sintaxe sofisticada que pode substituir
.filter
e.map
com afor(a of b)
sintaxe. Aqui está um exemplo:Como você pode ver, as duas linhas não são tão diferentes, exceto a segunda que não contém as palavras-chave volumosas e as funções de seta. Mas isso explica apenas o pedido
.filter().map()
; o que acontece se você tiver.map().filter()
? Isso depende da situação:Ou que se você quer quer
.map
ou.filter
? Bem, geralmente resulta menos OK:Portanto, meu conselho é usar compreensões matriz onde quer que você costuma usar
.map
e.filter
, mas não apenas um ou o outro.Compreensões de string
Uma coisa boa sobre as compreensões do ES7 é que, diferentemente de funções específicas de matrizes como
.map
e.filter
, elas podem ser usadas em qualquer objeto iterável, não apenas em matrizes. Isso é especialmente útil ao lidar com strings. Por exemplo, se você deseja executar cada caracterec
em uma string através dec.charCodeAt()
:São dois bytes salvos em uma escala bastante pequena. E se você quiser filtrar certos caracteres em uma string? Por exemplo, este mantém apenas letras maiúsculas:
Hmm, isso não é mais curto. Mas se combinarmos os dois:
Uau, um total de 10 bytes salvos!
Outra vantagem da compreensão de strings é que strings codificados economizam um byte extra, pois você pode omitir o espaço após
of
:Indexação
As compreensões de matriz tornam um pouco mais difícil obter o índice atual na string / array, mas isso pode ser feito:
A principal coisa a ter cuidado é garantir que o índice seja incrementado toda vez, e não apenas quando uma condição for atendida.
Compreensões do gerador
As compreensões de gerador têm basicamente a mesma sintaxe que as compreensões de matriz; basta substituir os parênteses por parênteses:
Isso cria um gerador que funciona da mesma maneira que uma matriz, mas essa é uma história para outra resposta.
Sumário
Basicamente, embora as compreensões sejam geralmente mais curtas
.map().filter()
, tudo se resume às especificidades da situação. É melhor tentar nos dois sentidos e ver qual funciona melhor.PS Sinta-se livre para sugerir outra dica relacionada à compreensão ou uma maneira de melhorar essa resposta!
fonte
(x,y)=>[...Array(y-x)].map(a=>x++)
x=>[...Array(x).keys()]
n=>[for(x of Array(n).keys())if(/1/.test(x))x]
(salva 7 bytes) #As expressões de função no ES6 usam a notação de seta e ajudam muito a salvar bytes se comparados com a versão do ES5:
Se sua função tiver apenas um parâmetro, você poderá omitir os parênteses para salvar dois bytes:
Se sua função não possui parâmetros, declare-a como se tivesse uma para salvar um byte:
Cuidado: as funções de seta não são exatamente iguais
function () {}
. As regras parathis
são diferentes (e melhor IMO). Veja documentosfonte
this
etc.f=(...x)=>x
teria issof(1,2,3) => [1,2,3]
.(x,y)=>...
que você pode salvar um byte com currying , substituindo-ox=>y=>...
O uso
eval
de funções de seta com várias instruções e umreturn
Um dos truques mais ridículos que já encontrei ...
Imagine uma função simples de seta que precise de várias instruções e a
return
.Uma função simples que aceita um único parâmetro
a
, que itera sobre todos os números inteiros[0, a)
e os prende no final da cadeia de saídao
, que é retornada. Por exemplo, chamar isso4
como o parâmetro renderia0123
.Observe que essa função de seta teve que ser colocada entre chaves
{}
e ter umareturn o
no final.Essa primeira tentativa pesa 39 bytes .
Não é ruim, mas usando
eval
, podemos melhorar isso.Essa função removeu os colchetes e a instrução de retorno envolvendo o código em
eval
e simplesmente fazendo a última instrução naeval
avaliação parao
. Isso faz com que oeval
retornoo
, que por sua vez faz com que a função retorneo
, já que agora é uma única instrução.Essa tentativa aprimorada pesa 38 bytes , economizando um byte do original.
Mas espere, tem mais! As declarações Eval retornam qualquer que seja sua última declaração avaliada. Nesse caso,
o+=i
avalia comoo
, portanto, não precisamos do;o
! (Obrigado, edc65!)Essa tentativa final pesa apenas 36 bytes - uma economia de 3 bytes em relação ao original!
Essa técnica pode ser estendida a qualquer caso geral em que uma função de seta precise retornar um valor e ter várias instruções (que não possam ser combinadas por outros meios)
torna-se
salvando um byte.
Se
statement2
avalia parav
, isso pode sereconomizando um total de 3 bytes.
fonte
;o
- experimentá-lo:a=>eval('for(o="",i=0;i<a;i++)o+=i')
Preferir novas linhas de sequência de modelo sobre "\ n"
Isso começará a render até mesmo um único caractere de nova linha no seu código. Um caso de uso pode ser:
(16 bytes)
(15 bytes)
Atualização: Você pode até deixar de fora as chaves devido a seqüências de caracteres de modelo marcadas (obrigado, edc65!):
(13 bytes)
fonte
Matrizes de preenchimento - valores estáticos e intervalos dinâmicos
Originalmente, deixei esses comentários como compreensivos, mas, como esse post foi focado principalmente em compreensões, achei que seria bom atribuir a isso seu próprio lugar.
O ES6 nos deu a capacidade de preencher matrizes com valores estáticos sem o uso de loops:
Ambos retornam uma matriz de comprimento x, preenchida com o valor 0.
Se você deseja preencher matrizes com valores dinâmicos (como um intervalo de 0 ... x), no entanto, o resultado é um pouco mais longo (embora ainda menor do que o modo antigo):
Ambos retornam uma matriz de comprimento x, começando com o valor 0 e terminando em x-1.
O motivo pelo qual você precisa estar
.fill()
lá é porque simplesmente inicializar uma matriz não permitirá que você a mapeie. Ou seja, fazerx=>Array(x).map((a,i)=>i)
retornará uma matriz vazia. Você também pode contornar a necessidade de preenchimento (e, assim, torná-lo ainda mais curto) usando o operador de dispersão da seguinte forma:Usando o operador e a
.keys()
função spread , agora você pode fazer um curto intervalo de 0 ... x:Se você deseja um intervalo personalizado de x ... y, ou um intervalo especializado completo (como números pares), pode se livrar
.keys()
e usar.map()
, ou usar.filter()
, com o operador spread:fonte
x=>Array(x).fill(i=0).map(a=>i++)
Além disso, não tenho certeza de que o 0 in.fill(0)
seja necessário. Você já tentou isso sem?a=>a%2-1
funciona bem, assim comoa=>a%2<1
.[...Array(x)]
funciona tão bem quantoArray(x).fill()
é 2 bytes mais curto.x=>[...Array(x)].map((a,i)=>i)
1/4
exemplo seria mais curto[0,0,0,0]
e 2) as funções estritas serão específicas da implementação, portanto, não retornarão um comprimento confiável (Map
32 bytes no Chrome, mas 36 bytes no Firefox).Retornando valores em funções de seta
É de conhecimento geral que, se uma única instrução segue a declaração da função da seta, ela retorna o resultado dessa instrução:
-7 bytes
Portanto, quando possível, combine várias instruções em uma. Isso é feito com mais facilidade, colocando as instruções entre parênteses e separando-as com vírgulas:
-8 bytes
Mas se houver apenas duas instruções, geralmente é possível (e mais curto) combiná-las com
&&
ou||
:-9 bytes
Finalmente, se você estiver usando o mapa (ou similar) e precisar retornar um número e garantir que o mapa nunca retornará uma matriz de um comprimento com um número, você pode retornar o número com
|
:fonte
Hacks aleatórios de string de modelo
Essa função reproduz duas strings (ou seja, se transforma
"abc","de"
em"adbec"
):Observe que isso só funciona quando
x
for maior quey
. Como isso funciona, você pergunta?String.raw
foi projetado para ser uma tag de modelo, assim:Isso basicamente chama
String.raw(["x: ", "\ny: ", "\nx + y: ", ""], x, y, x + y)
, embora não seja tão simples. A matriz de modelos também possui umaraw
propriedade especial , que é basicamente uma cópia da matriz, mas com as strings brutas.String.raw(x, ...args)
basicamente retornax.raw[0] + args[0] + x.raw[1] + args[1] + x.raw[2] + ...
e assim por diante atéx
ficar sem itens.Então, agora que sabemos como
String.raw
funciona, podemos usá-lo para nossa vantagem:Claro, para esse último,
f=(x,y)=>x.split``.join(y)
é bem mais curto, mas você entendeu.Aqui estão algumas funções de riffling que também funcionam se
x
ey
têm o mesmo comprimento:Você pode aprender mais sobre o
String.raw
MDN .fonte
Como jogar golfe com recursão
A recursão, embora não seja a opção mais rápida, é muitas vezes a mais curta. Geralmente, a recursão é mais curta se a solução puder ser simplificada para uma parte menor do desafio, especialmente se a entrada for um número ou uma sequência. Por exemplo, se
f("abcd")
pode ser calculado a partir de"a"
ef("bcd")
, geralmente é melhor usar recursão.Tomemos, por exemplo, fatorial:
Neste exemplo, a recursão é obviamente muito menor do que qualquer outra opção.
Que tal a soma dos códigos:
Essa é mais complicada, mas podemos ver que, quando implementada corretamente, a recursão economiza 4 bytes
.map
.Agora vamos ver os diferentes tipos de recursão:
Pré-recursão
Este é geralmente o tipo mais curto de recursão. A entrada é dividida em duas partes
a
eb
, e a função calcula algo coma
ef(b)
. Voltando ao nosso exemplo fatorial:Nesse caso,
a
é n ,b
é n-1 e o valor retornado éa*f(b)
.Nota importante: Todas as funções recursivas devem ter uma maneira de parar de repetir quando a entrada é pequena o suficiente. Na função fatorial, isso é controlado com o
n? :1
, ou seja, se a entrada for 0 , retorne 1 sem chamarf
novamente.Pós-recursão
Pós-recursão é semelhante à pré-recursão, mas um pouco diferente. A entrada é dividida em duas partes
a
eb
, e a função calcula algo coma
, depois chamaf(b,a)
. O segundo argumento geralmente tem um valor padrão (ou sejaf(a,b=1)
).A pré-recursão é boa quando você precisa fazer algo especial com o resultado final. Por exemplo, se você deseja o fatorial de um número mais 1:
Mesmo assim, no entanto, pós- nem sempre é mais curto do que usar pré-recursão dentro de outra função:
Então, quando é mais curto? Você pode perceber que a pós-recursão neste exemplo requer parênteses em torno dos argumentos da função, enquanto a pré-recursão não. Geralmente, se as duas soluções precisarem de parênteses em torno dos argumentos, a pós-recursão será cerca de 2 bytes mais curta:
(programas aqui retirados desta resposta )
Como encontrar a solução mais curta
Geralmente, a única maneira de encontrar o método mais curto é tentar todos eles. Isso inclui:
.map
(para cadeias de caracteres,[...s].map
ous.replace
; para números, você pode criar um intervalo )E essas são apenas as soluções mais comuns; a melhor solução pode ser uma combinação desses, ou até algo completamente diferente . A melhor maneira de encontrar a solução mais curta é tentar de tudo .
fonte
Maneiras mais curtas de fazer
.replace
Se você deseja substituir todas as instâncias de uma substring exata por outra em uma string, a maneira óbvia seria:
No entanto, você pode fazer 1 byte menor:
Observe que isso não é mais curto se você quiser usar qualquer recurso de regex além do
g
sinalizador. No entanto, se você estiver substituindo todas as instâncias de uma variável, geralmente é muito menor:Às vezes, você deseja mapear cada caractere em uma string, substituindo cada um por outra. Muitas vezes me vejo fazendo isso:
No entanto,
.replace
é quase sempre mais curto:Agora, se você deseja mapear cada caractere em uma string, mas não se importa com a string resultante,
.map
geralmente é melhor porque você pode se livrar de.join``
:fonte
/\w/g
) estiverem interessados, o uso de replace será muito melhor como nesta demonstração .Gravando literais RegEx com
eval
O construtor regex pode ser muito volumoso devido ao nome longo. Em vez disso, escreva um literal com eval e backticks:
Se a variável
i
for igual afoo
, isso irá gerar:Isso é igual a:
Você também pode usar
String.raw
para evitar ter que escapar repetidamente das barras invertidas\
Isso produzirá:
Qual é igual a:
Tenha em mente!
String.raw
ocupa muitos bytes e, a menos que você tenha pelo menos nove barras invertidas,String.raw
será mais longo.fonte
new
lá dentro, portanto, usando o construtor é realmente mais curto para o segundo exemplo.forEach
vsfor
loopsSempre prefira
.map
qualquer loop for. Economia fácil e instantânea.fonte
Usando contadores não inicializados na recursão
Nota : Estritamente falando, isso não é específico para o ES6. No entanto, faz mais sentido usar e abusar da recursão no ES6, devido à natureza concisa das funções das setas.
É bastante comum encontrar uma função recursiva que usa um contador
k
inicialmente definido como zero e incrementado a cada iteração:Sob certas circunstâncias, é possível omitir a inicialização desse contador e substituir
k+1
por-~k
:Esse truque normalmente salva 2 bytes .
Por que e quando isso funciona?
A fórmula que torna possível é
~undefined === -1
. Portanto, na primeira iteração,-~k
será avaliado como1
. Nas próximas iterações,-~k
é essencialmente equivalente a-(-k-1)
igual ak+1
, pelo menos para números inteiros no intervalo [0… 2 31 -1].No entanto, você deve garantir que
k = undefined
a primeira iteração não perturbe o comportamento da função. Você deve ter especialmente em mente que a maioria das operações aritméticas que envolvemundefined
resultará emNaN
.Exemplo 1
Dado um número inteiro positivo
n
, esta função procura o menor número inteirok
que não se dividen
:Pode ser reduzido para:
Isso funciona porque
n % undefined
éNaN
, o que é falso. Esse é o resultado esperado na primeira iteração.[Link para a resposta original]
Exemplo 2
Dado um número inteiro positivo
n
, esta função procura por um número inteirop
que(3**p) - 1 == n
:Pode ser reduzido para:
Isso funciona porque
p
não é usado de todo na primeira iteração (n<k
sendo falso).[Link para a resposta original]
fonte
Funções ES6
Matemática
Math.cbrt(x)
salva caracteres queMath.pow(x,1/3)
.3 caracteres salvos
Math.hypot(...args)
é útil quando você precisa da raiz quadrada da soma dos quadrados dos args. Tornar o código ES5 para fazer isso é muito mais difícil do que usar um built-in.A função
Math.trunc(x)
não seria útil, poisx|0
é mais curta. (Obrigado Mwr247!)Existem muitas propriedades que exigem muito código no ES5, mas mais fáceis no ES6:
Math.acosh
,asinh
,atanh
,cosh
,sinh
,tanh
. Calcula o equivalente hiperbólico das funções trigonométricas.Math.clz32
. Pode ser possível fazer no ES5, mas agora é mais fácil. Conta zeros à esquerda na representação de 32 bits de um número.Há muito mais, por isso estou indo só para listar alguns:
Math.sign
,Math.fround
,Math.imul
,Math.log10
,Math.log2
,Math.log1p
.fonte
Math.trunc(x)
é quatro vezes maior quex|0
.Math.hypot(a,b) => Math.sqrt(a*a+b*b)
(3 bytes a mais; fica ainda mais com mais argumentos),Math.sign(a) => (a>0)-(a<0)
(1 byte mais curto, mas precisa de parênteses em alguns casos; pode não funcionar comNaN
)Otimizando pequenos intervalos constantes para
map()
Contexto
map()
for
pode ser substituído por:
ou mais comumente:
Array(N)
NB : O comprimento do código de retorno de chamada
F(i)
não é contado.Otimizações sem contador
NB : O comprimento do código de retorno de chamada
F()
não é contado.fonte
2**26
ser2**29
?.keys()
, você não precisa de um lambda:[...Array(10).keys()].map(do_something_with)
Atribuições de reestruturação
O ES6 introduz uma nova sintaxe para desestruturar atribuições, ou seja, cortar um valor em partes e atribuir cada parte a uma variável diferente. Aqui estão alguns exemplos:
Strings e matrizes
Objetos
Essas atribuições também podem ser usadas em parâmetros de função:
fonte
Mais uma maneira de evitar
return
Você sabe que deve usar eval para funções de seta com várias instruções e um retorno . Em alguns casos incomuns, você pode economizar mais usando uma subfunção interna.
Eu digo incomum porque
O resultado retornado não deve ser a última expressão avaliada no loop
Deve haver (pelo menos) 2 inicializações diferentes antes do loop
Nesse caso, você pode usar uma subfunção interna sem retorno, tendo um dos valores iniciais passados como parâmetro.
Exemplo Encontre o recíproco da função soma da exp para valores em um intervalo de a a b.
O longo caminho - 55 bytes
Com eval - 54 bytes
Com uma função interna - 53 bytes
Observe que, sem a exigência de um limite de intervalo menor
a
, eu posso mesclar as inicializações de ie er, e a versão eval é mais curta.fonte
a
(i,b)=>{for(r=0;i<=b;i++)r+=Math.exp(i);return 1/r}
return a/r
seria um exemplo melhor(a,b)=>1/eval("for(r=0,i=a;i<=b;i++)r+=Math.exp(i)")
e, neste caso,(i,b)=>1/eval("for(r=0;i<=b;)r+=Math.exp(i++)")
Usando a sintaxe de currying para funções diádicas e recursivas
Funções diádicas
Sempre que uma função usa exatamente dois argumentos sem valores padrão, o uso da sintaxe de currying salva um byte.
Antes
Chamado com
f(a,b)
Depois de
Chamado com
f(a)(b)
Nota : Esta postagem no Meta confirma a validade dessa sintaxe.
Funções recursivas
O uso da sintaxe de currying também pode salvar alguns bytes quando uma função recursiva usa vários argumentos, mas só precisa atualizar alguns deles entre cada iteração.
Exemplo
A função a seguir calcula a soma de todos os números inteiros no intervalo
[a,b]
:Como
a
permanece inalterado durante todo o processo, podemos salvar 3 bytes usando:Nota : Conforme observado por Neil nos comentários, o fato de um argumento não ser passado explicitamente para a função recursiva não significa que ele deva ser considerado imutável. Se necessário, poderíamos modificar
a
dentro do código de função coma++
,a--
ou qualquer sintaxe semelhante.fonte
a=>F=b=>a>b?0:a+++F(b)
, modificandoa
para cada chamada recursiva. Isso não ajuda nesse caso, mas pode salvar bytes em casos com mais argumentos.Função de teste de primazia
A seguinte função de 28 bytes retorna
true
para números primos efalse
não primos:Isso pode ser facilmente modificado para calcular outras coisas. Por exemplo, essa função de 39 bytes conta o número de números primos menor ou igual a um número:
Se você já possui uma variável
n
que deseja verificar quanto à primalidade, a função da primalidade pode ser bastante simplificada:Como funciona
Nota: Isso falhará com um erro "muita recursão" quando chamado com uma entrada suficientemente grande, como 12345. Você pode contornar isso com um loop:
fonte
x==1
provavelmente pode serx<2
uma economia.1
ou0
(porquex
seria0
ou-1
, respectivamente)!~-x
para -0 bytes.Array#concat()
e o operador spreadIsso depende muito da situação.
Combinando várias matrizes.
Prefira a função concat, a menos que seja clonada.
0 bytes salvos
3 bytes desperdiçados
3 bytes salvos
6 bytes salvos
Prefira usar uma matriz já existente para
Array#concat()
.Fácil 4 bytes salvos
fonte
Retornar resultado intermediário
Você sabe que, usando o operador vírgula, é possível executar uma sequência de expressões retornando o último valor. Mas abusando da sintaxe literal da matriz, você pode retornar qualquer valor intermediário. É útil em .map (), por exemplo.
fonte
.join('')
pode ser #.join``
Definir padrões de parâmetros de função
Este é realmente útil ...
No entanto, certifique-se de entender que algo
_=>_||'asdf'
mais curto é quando você passa apenas um argumento (útil) para a função.fonte
_=>_||'asdf'
é geralmente mais curto na maioria dos casos"asdf"
para uma entrada de""
(string vazia).undefined
, mesmo se você passar explicitamente esse valor. Por exemplo,[...Array(n)].map((a,b,c)=>b)
sempre passaundefined
paraa
e, portanto, você pode fornecer um valor padrão para ele (embora não em termos deb
).Use em
eval
vez de chaves para funções de setaAs funções de seta são impressionantes. Eles assumem a forma
x=>y
, ondex
é um argumento ey
é o valor de retorno. No entanto, se você precisar usar uma estrutura de controle, comowhile
, teria que colocar chaves, por exemplo=>{while(){};return}
. No entanto, podemos contornar isso; felizmente, aeval
função pega uma string, avalia essa string como código JS e retorna a última expressão avaliada . Por exemplo, compare estes dois:Podemos usar uma extensão desse conceito para reduzir ainda mais o nosso código: aos olhos de
eval
, as estruturas de controle também retornam sua última expressão avaliada. Por exemplo:fonte
Operações lógicas de golfe no ES6
"GLOE (S6)"
Lógica geral
Digamos que você tenha construído declarações
s
et
. Veja se você pode usar qualquer uma das seguintes substituições:(Eles podem não funcionar se o pedido estiver errado; ou seja,
+
e*
têm uma precedência de pedido menor que||
e&&
).Além disso, aqui estão algumas expressões lógicas úteis:
s
out
é verdade / XOR:s^t
s
et
são o mesmo valor de verdade:!s^t
ous==t
Lógica de matriz
Todos os membros da
a
condição de satisfaçãop
:Pelo menos um membro da
a
condição satisfazp
:Nenhum membro da
a
condição de satisfazerp
:!a.some(p)
.O elemento
e
existe na matriza
:Elemento
e
que não existe em ordema
:fonte
&&
e||
comox?y:x
ex?x:y
, respectivamente. Mas posso ver como isso seria útil em mais programas baseados em lógica. O único problema+
seria que, por exemplo,3
e-3
ambos são verdadeiros, mas3+-3
não são.-
também poderia funcionar, ses != t
.a.filter(t=>t==e).length==a.length
está incorreto. Deveria ser!a.filter(t=>t==e).length
Encurte chamadas de função repetidas
Se você repetiu chamadas para uma função com um nome longo, como manipulação de tela:
A maneira tradicional de encurtar isso seria usar o apelido de nome da função:
Se você tiver chamadas suficientes, a melhor maneira é criar uma função que faça o trabalho para você:
Se a maioria das chamadas de função estiver encadeada, você poderá fazer com que a função retorne por si mesma, permitindo cortar dois bytes de cada chamada sucessiva:
Exemplo de uso: 1 , 2
fonte
(l=::c.lineTo)(0,100)(100,100)(100,0)(0,0);c.stroke()
c.lineTo
não em si retornar naturalmente)Operador de ligação
::
O operador de ligação pode ser usado para ajudar a reduzir bytes em funções repetidas:
Além disso, se você quiser usar a função com um
this
exemplo diferente :fonte
Evitando vírgulas ao armazenar muitos dados
Se você possui muitos dados (por exemplo, índices, caracteres, ...) que precisa armazenar em uma matriz, é melhor deixar todas as vírgulas afastadas. Isso funciona melhor se todos os dados tiverem o mesmo comprimento de string, 1 obviamente sendo ideal.
43 bytes (linha de base)
34 bytes (sem vírgulas)
Se você estiver disposto a alterar o acesso à sua matriz , poderá reduzir ainda mais isso, armazenando os mesmos valores da seguinte forma:
27 bytes (mesmos dados, apenas altera o acesso ao array)
fonte