Que dicas gerais você tem para jogar golfe em JavaScript? Estou procurando idéias que possam ser aplicadas para codificar problemas de golfe em geral que sejam pelo menos um pouco específicos para JavaScript (por exemplo, "remover comentários" não é uma resposta).
Nota: Consulte também Dicas para jogar golfe no ECMAScript 6 e acima
code-golf
tips
javascript
mellamokb
fonte
fonte
var
)? E o código de golfe JavaScript deve ser uma função ou gerar algo diretamente? Sinceramente, acho que isso pode fazer muita diferença.Respostas:
Fantasia para loops
você pode usar o padrão para loop de maneiras não padronizadas
é essencialmente equivalente a:
portanto, um bom truque é escrever seu código com um
while
loop e depois dividi-lo nasa,b,c
partes em umfor
loop.Alguns exemplos que escrevi :
Encadear seus setters
Se você estiver inicializando ou redefinindo vários valores, encadeie o valor a todas as variáveis que precisam:
Fundição implícita
Não verifique seus tipos, use-os como estão.
parseInt()
custa10
caracteres. Se você precisar eliminar uma string, seja criativo:Evitar ponto e vírgula
JavaScript tem inserção automática de ponto e vírgula. Use-o com frequência e bem.
One-liners
Economize entre colchetes, empurrando o máximo possível em linhas únicas ou parâmetros:
Operadores de incremento / decréscimo
e
pode ser facilmente reescrito como
e
respectivamente.
Use
this
ou emself
vez dewindow
no contexto globaleconomia de 2 caracteres auto-explicativa.
Use notação de colchete para acesso repetido à propriedade
Esse é definitivamente um ato de equilíbrio entre o comprimento do nome da propriedade e o número de acessos. Em vez de chamar
a.longFunctionName()
com notação de ponto duas vezes, é mais curto salvar o nome e chamar a função via notação entre colchetes:-vs-
isso é especialmente eficaz com funções como as
document.getElementById
quais podem ser reduzidas ad[e]
.Nota:
Com a notação entre colchetes, o custo é de
6 + name.length
caracteres na primeira vez. Cada acesso subsequente tem um custo de3
caracteres.Para notação de pontos, todos os acessos custam
name.length + 1
(+1 para os.
) caracteres.Use este método se
6 + name.length + (3 * (accesses - 1)) < accesses * (name.length + 1)
.len = comprimento do nome da propriedade
i = acessos mínimos para aproveitar
O número de acessos também pode abranger vários objetos. Se você acessar
.length
4 ou mais vezes em matrizes diferentes, poderá usar a mesma variável segurando a string'length'
.fonte
c = ~~a-~~b
deveria serc = ~~a+~~b
. Além disso, você pode converter implicitamente em número inteiro usando|0
, por exemploMath.random()*6|0
.a
eb
são cadeias, você pode fazer+a+b
a conversão para número e adicioná-las.d- -b
no meu código algum dia ...a.f=a.longfunctionname;a.f(b);a.f(c);a.f(d)
Divisão com números para salvar as aspas:
fonte
.split`...`
"alpha,bravo,charlie".split`,`
Use o operador de vírgula para evitar chaves (também se aplica a C ):
Ao invés de
que é um caractere mais longo.
fonte
Menor geração de números aleatórios
Se você precisar de um booleano aleatório (
0
ou1
):Se você precisar de um número inteiro aleatório
0 <= n < 1337
:Isso funciona porque a
Date
é armazenado internamente em JavaScript como a quantidade de milissegundos desde uma época, enew Date
está sendo coagido123somebignumber456
quando você tenta fazer cálculos inteiros nele.Certamente, esses números "aleatórios" realmente não serão tão aleatórios, especialmente se você os chamar várias vezes em rápida sucessão, então lembre-se disso.
fonte
Você pode usar a forma literal de objeto de get / set para evitar o uso da palavra-chave
function
.fonte
Este é menos conhecido e menos usado, mas pode ser impressionante se usado na situação certa. Considere uma função que não aceita argumentos e sempre retorna um número diferente quando chamado, e o número retornado será usado em um cálculo:
Normalmente, você pode encurtar essa função usando um nome de variável com uma letra:
Uma maneira melhor de reduzir o comprimento é abusar
valueOf
, o que permite economizar 2 caracteres por chamada. Útil se você chamar a função mais de 5 vezes:fonte
let a=[5,6,7,8,9,10,11,12].map(x=>x*Math.random()|0)
oulet a=Array(7).map((_,i)=>i*Math.random()|0+5)
36 ou 42 bytes salvos, respectivamente.r()
ou reduzi-lo?r={valueOf:Math.random}
Isso é apenas genial: DAproveitando os operadores de curto-circuito
Em vez de
if
instruções longas ou usar operadores ternários, você pode usar&&
e||
reduzir seu código. Por exemplo:pode se tornar
O
||
operador é frequentemente usado dessa maneira para definir padrões:É o mesmo que escrever
Criando seqüências repetitivas usando Array
Se você deseja inicializar uma cadeia longa de um caractere específico, pode fazê-lo criando uma matriz com um comprimento de n + 1 , em que n é o número de vezes que deseja repetir o caractere:
Quanto maior a corda, maior a economia.
Analisando números
Use
+
e~
operadores em vez deparseFloat()
ouparseInt()
ao unir um tipo de sequência que é apenas um número para um tipo de número:Seja cauteloso, porém, outros tipos podem ser combinados com esses operadores (por exemplo,
true
se tornariam1
) uma string vazia ou uma string contendo apenas espaço em branco0
. Isso pode ser útil em determinadas circunstâncias, no entanto.fonte
str.repeat(count)
Esgueirar a inicialização da variável na chamada prompt () para obter a entrada do usuário
ao invés de usar
Como efeito colateral, ele exibe o valor de entrada na janela de prompt enquanto salva 1 caractere.
fonte
[1,2,3].join('',i=5)
nos casos em que salva um par de chaves.i=5,[1,2,3].join()
.Combinar aninhado para loops:
Exemplo com valores diferentes para
i
/j
:fonte
i*j
e os operadores de divisão / módulo recuperam os valores individuais dei
ej
.Atalhos Unicode
Se você usa uma propriedade embutida em um grande desafio de golfe, pode alias cada propriedade a um equivalente de um caractere:
Depois de executar o código acima, você pode usá-lo assim:
"foo".Č(/.*/,'bar') // replaces foo with bar
Isso custa 118 bytes, portanto pode não ser útil em determinadas situações
Pode ser dependente do navegador e não tenho certeza se é mais curto
with(Array){join(foo),...}
ou que define variáveis como propriedades usadas,with(Array){j=join,m=map...}
mas ainda vale a pena mencionar.fonte
Math
porque não possui um.prototype
atributo. RemovendoMath
, no entanto, consegui jogar isso em um snippet de 114 bytes que os atribui a letras de byte único. Você pode encontrá-lo aqui .À
-ÿ
, que ainda possui 1 byte na codificação ISO-8859-1 (suportada pelo JS). Infelizmente no Firefox 50, infelizmente, o.localeCompare
método é ativado×
, mas isso normalmente não deve ser um problema. fonteConverter um
while
loop em umfor
loop geralmente é equivalente:Mas a segunda forma pode ter a inicialização variável combinada:
Observe que o segundo formulário é um caractere menor que o primeiro.
fonte
Abuso de exceção
no caso de literais de cadeia / caracteres serem proibidos, você pode usar um bloco try catch:
agora
str
é igual"something"
se forem necessárias mais strings, você pode encadear com um número (por exemplo, zeros)
agora
arr
é igual["something", "foo", "bar", " is not defined"]
fonte
Se você estiver inicializando uma variável
1
em todas as iterações de um loop (por exemplo, redefinindo uma variável em um loop externo para um loop interno), como o seguinte (da minha resposta a esta pergunta ):Como o resultado de uma condição como
j++<=n
é1
sempre que é verdadeiro, é possível atribuir a condição diretamente à variável (porque quando ela se torna falsa, o loop para de ser executado e não importa mais):Você geralmente pode salvar 2 caracteres usando esse método. Atenciosamente,
@ugoren
para a idéia nos comentários a essa resposta.Para outro exemplo, também apliquei esse truque na minha resposta aqui com a expressão
w=r=++c<S.length
no loop for externo, salvando um total de 4 caracteres.fonte
Se você puder aceitar scripts específicos do Spidermonkey (por enquanto), poderá usar as funções de seta do ECMAScript 6 . Em vez de escrever código como o seguinte.
Você pode encurtar assim.
fonte
Se você precisar verificar o NaN, não use
isNaN(x)
, mas usex!=x
, que é mais curto e também funciona.Observe que isso só funciona se
typeof(x) === "number"
; se for uma string, por exemplo,isNaN("string")
retornatrue
, mas"string" != "string"
retornafalse
. Agradecemos a Cyoce por apontar isso!fonte
isNaN("string")
retornostrue
, enquanto"string"!="string"
retornosfalse
(obviamente)if(!x){
, se estiver detectandoNaN
explicitamente.x
para número, o+x!=+x
torna equivalente aisNaN(x)
, ainda assim, 2 caracteres mais curtos. Então,+"string"!=+"string"
retorna verdadeiro.Soma / produto / quociente da matriz
ES5 : 17 bytes
ES6 : 15 bytes
É claro que você pode trocar
+
por qualquer coisa que desejar, por exemplo,*
por produto ou/
por quociente.fonte
Use uma operação bit a bit para arredondar um número para zero:
(Fonte: tombamento de dados aleatórios )
A precedência do operador determina quais serão mais curtos no seu programa.
fonte
n=prompt()|0
,.Math.floor
é terrivelmente lento ... quase não deve ser usado, eu diria.Dica de loop I
Você pode salvar um
1
caractere ao fazer um loop alterando oi
da última vez em que foi usado:Nota: também funciona
--
(mas modifique o loop de acordo para evitar loop infinito)Dica de loop II
Existem certos cenários em que você pode salvar um personagem jogando com o operador e valores incrementais:
Nota: você precisa prestar atenção quando, por exemplo
0 to -1
. e9 to 10, 99 to 100
, então brinque até encontrar uma maneira de salvar o personagemfonte
Use em
^
vez de!=
ou==
ao comparar com um número inteiroSubstituir chamadas para funções matemáticas internas por expressões mais curtas
fonte
-
vez de!=
para números inteiros; Por exemplo,n!=1?a:b
seria equivalente an-1?a:b
Algo digno de nota é que você pode usar uma string no lugar de zero em alguns casos para salvar alguns bytes aqui e ali em loops:
fonte
Muito simples, mesmo assim, ninguém havia mencionado.
Se você estiver usando
Math.min()
ouMath.max()
puder salvar 6 caracteres, faça o seguinte:fonte
Arredondamento
Eu sei que alternativas
Math.floor()
foram postadas, mas e as outras?Pavimentação:
Arredondamento:
Teto:
fonte
0|x+1
basta adicionar 1 se o número do qual você deseja encontrar o teto já for um número inteiro. Uma alternativa (principalmente) segura é0|x+1-1e9
, mas isso é apenas três bytes mais curto.0|x+1-1e-9
?x%1?-~x:x
(9 caracteres) é uma alternativa melhor. No entanto, como as alternativas de piso0|x
e~~x
, ele só funciona para números positivos.Nos casos em que você está usando o operador ternário para escolher entre dois números , e o condicional é um booleano ou um número
1 or 0
, você pode executar operações matemáticas:Nota: Além disso, você precisará remover o desnecessário
0-
,+0
,+-
etc.Nota 2: existe um caso isolado em que
(x) !== (x?1:0)
, comox
deve ser,typeof === "number"
para que funcione. No entanto, no caso de(-x)
funcionar muito bem.Nota 3: Caso não encontre economia, basta usar o antigo
(x?y:z)
Anteriormente, eu pensava que o método B nunca poderia vencer A, no entanto, existem exceções:
Criei um projeto no github que simplifica para nós ( demonstração do jsFiddle )
fonte
void 0
(não é uma função, mas uma palavra-chave) não é um valor, simplesmente retornaundefined
.a
deve ser 1 ou 0 para que ele funcionetl; dr: use os recursos do ES6!
Funções de seta
Doc: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/arrow_functions
Exemplo:
fonte
for
..of
é legal. Mesmo menor do quefor each
..in
.b = [s(x) for (x of a)]
.Literais de abuso
A amostra recente: verifique se
"c"
está em maiúscula ou minúscula, não importa se não está em letrafonte
String({})
dá"[object Object]"
.Como comparar um número com a ajuda de como os números se transformam em booleanos:
Se você deseja verificar se algo é igual a um número positivo , pode subtrair esse valor e reverter o que estava dentro dos blocos
if
eelse
:E caso você queira comparar com um número negativo (* diferente de
-1
), basta adicionar esse número em vez de subtrair.* bem, você certamente pode usar
x.indexOf(y) + 1
, mas no caso especial de-1
você ter a oportunidade de usá-lo~x.indexOf(y)
.fonte
Use o recurso "fechamento de expressão" fora do padrão da Mozilla para salvar muitos caracteres em um script que só precisa funcionar nos mecanismos SpiderMonkey / Firefox ou Rhino. Por exemplo,
torna-se
Veja a página Estouro de pilha para mais truques.
fonte
->bar
let foo = () => bar;
ironicamente mais curto que o código de golfe acima.foo=_=>bar
ainda mais curto.Use em
if(~a.indexOf(b))
vez deif(a.indexOf(b)!=-1)
fonte
Em vez de escrever,
true
você pode usar!0
.fonte
!1
parafalse
.1
paratrue
e0
parafalse
, a menos que você realmente precise dos valores literais.Transformando em um booleano :
Nota: Isso muda
0
,""
,false
,null
,undefined
eNaN
parafalse
(tudo mais paratrue
)fonte