¿Qué consejos generales tienes para jugar al golf en JavaScript? Estoy buscando ideas que puedan aplicarse a los problemas de código de golf en general que sean al menos algo específicos de JavaScript (por ejemplo, "eliminar comentarios" no es una respuesta).
Nota: Consulte también Consejos para jugar golf en ECMAScript 6 y superior
code-golf
tips
javascript
mellamokb
fuente
fuente
var
)? ¿Y el código de golf JavaScript debería ser una función o generar algo directamente? Sinceramente, creo que esto puede hacer mucha diferencia.Respuestas:
Fantasía para bucles
puede usar el bucle estándar para formas no estándar
es esencialmente equivalente a:
así que un buen truco es escribir su código con un
while
bucle y luego dividirlo ena,b,c
partes en unfor
bucle.Un par de ejemplos que he escrito :
Encadena a tus acomodadores
Si está inicializando o restableciendo múltiples valores, encadene el valor a todas las variables que lo necesitan:
Casting implícito
No verifiques tus tipos, solo úsalos como están.
parseInt()
cuesta10
personajes. Si necesita expulsar de una cadena, sea creativo:Evitar los punto y coma
JavaScript tiene inserción automática de punto y coma. Úselo a menudo y bien.
One-liners
Ahorre entre paréntesis empujando tanto como sea posible en líneas individuales o parámetros:
Operadores de aumento / disminución
y
puede reescribirse fácilmente como
y
respectivamente.
Usar
this
o enself
lugar dewindow
en contexto globalAhorro autoexplicativo de 2 caracteres.
Use la notación de paréntesis para repetir el acceso a la propiedad
Este es definitivamente un acto de equilibrio entre la longitud del nombre de la propiedad y el número de accesos. En lugar de llamar
a.longFunctionName()
dos veces con notación de punto, es más corto guardar el nombre y llamar a la función mediante notación de paréntesis:-vs-
Esto es especialmente efectivo con funciones como las
document.getElementById
que se pueden reducir ad[e]
.Nota:
Con la notación de corchetes, el costo son
6 + name.length
caracteres la primera vez. Cada acceso posterior tiene un costo de3
caracteres.Para la notación de puntos, todos los accesos cuestan
name.length + 1
(+1 para los.
) caracteres.Use este método si
6 + name.length + (3 * (accesses - 1)) < accesses * (name.length + 1)
.len = longitud del nombre de la propiedad
i = accesos mínimos para aprovechar
El número de accesos también puede abarcar múltiples objetos. Si accede
.length
4 o más veces en diferentes matrices, puede usar la misma variable que contiene la cadena'length'
.fuente
c = ~~a-~~b
debería serc = ~~a+~~b
. Además, puede convertir implícitamente a entero usando|0
, por ejemploMath.random()*6|0
.a
yb
son cadenas, puede hacer+a+b
para convertir a número y agregarlas.d- -b
algún día usaré mi código ...a.f=a.longfunctionname;a.f(b);a.f(c);a.f(d)
División con números para guardar las comillas:
fuente
.split`...`
"alpha,bravo,charlie".split`,`
Use el operador de coma para evitar llaves (también se aplica a C ):
En lugar de
que es un personaje más largo.
fuente
Generación de números aleatorios más corta
Si necesita un booleano aleatorio (
0
o1
):Si necesita un entero aleatorio
0 <= n < 1337
:Esto funciona porque a
Date
se almacena internamente en JavaScript como la cantidad de milisegundos desde una época, por lo quenew Date
se está coaccionando123somebignumber456
cuando intentas hacer matemáticas enteras en él.Por supuesto, estos números "aleatorios" realmente no serán tan aleatorios, especialmente si los llamas varias veces seguidas, así que tenlo en cuenta.
fuente
Puede usar la forma literal del objeto get / set para evitar usar la palabra clave
function
.fuente
Este es menos conocido y menos utilizado, pero puede ser impresionante si se usa en la situación correcta. Considere una función que no toma argumentos y siempre devuelve un número diferente cuando se llama, y el número devuelto se usará en un cálculo:
Normalmente puede acortar esta función usando un nombre de variable de una letra:
Una mejor manera de reducir la longitud es abusando
valueOf
, lo que le permite guardar 2 caracteres por invocación. Útil si llama a la función más de 5 veces:fuente
let a=[5,6,7,8,9,10,11,12].map(x=>x*Math.random()|0)
olet a=Array(7).map((_,i)=>i*Math.random()|0+5)
, 36 o 42 bytes guardados, respectivamente.r()
o acortarlo?r={valueOf:Math.random}
Eso es genial: DAprovechando los operadores de cortocircuito
En lugar de largas
if
declaraciones o el uso de operadores ternarios, puede utilizar&&
y||
acortar su código. Por ejemplo:puede llegar a ser
El
||
operador se usa a menudo de esta manera para establecer valores predeterminados:Esto es lo mismo que escribir
Crear cadenas repetitivas usando Array
Si desea inicializar una cadena larga de un carácter en particular, puede hacerlo creando una matriz con una longitud de n + 1 , donde n es el número de veces que desea repetir el carácter:
Cuanto más grande es la cuerda, mayor es el ahorro.
Analizando números
Use
+
y~
operadores en lugar deparseFloat()
oparseInt()
al fusionar un tipo de cadena que es solo un número con un tipo de número:Sin embargo, tenga cuidado, otros tipos pueden fusionarse con estos operadores (por ejemplo,
true
se convertirían1
) en una cadena vacía o se convertiría en una cadena que contiene solo un espacio en blanco0
. Sin embargo, esto podría ser útil en ciertas circunstancias.fuente
str.repeat(count)
Introducir la inicialización de la variable en la llamada prompt () para obtener la entrada del usuario
En lugar de usar
Como efecto secundario, muestra el valor de entrada en la ventana de solicitud al guardar 1 carácter.
fuente
[1,2,3].join('',i=5)
en los casos en que guarda un par de llaves.i=5,[1,2,3].join()
.Combinar anidados para bucles:
Ejemplo con diferentes valores para
i
/j
:fuente
i*j
y los operadores de división / módulo recuperan los valores individuales dei
yj
.Atajos Unicode
Si utiliza una gran propiedad incorporada en un gran desafío de golf, puede asignar un alias a cada propiedad con un equivalente de un personaje:
Después de ejecutar el código anterior, puede usarlo así:
"foo".Č(/.*/,'bar') // replaces foo with bar
Esto cuesta 118 bytes, por lo que podría no ser útil en ciertas situaciones
Puede depender del navegador y no estoy seguro de si es más corto
with(Array){join(foo),...}
o define variables como propiedades utilizadas,with(Array){j=join,m=map...}
pero vale la pena mencionarlo.fuente
Math
porque no tiene un.prototype
atributo. SinMath
embargo, al eliminarlo , logré convertir esto en un fragmento de 114 bytes que los asigna a todos a letras de un solo byte. Lo puedes encontrar aquí .À
-ÿ
, que todavía es de 1 byte cada uno en la codificación ISO-8859-1 (que apoya JS). En Firefox 50, desafortunadamente esto activa el.localeCompare
método×
, pero eso no debería ser un problema. fuenteConvertir un
while
bucle en unfor
bucle suele ser equivalente:Pero la segunda forma puede tener una inicialización variable combinada:
Observe que la segunda forma tiene un carácter más corto que la primera forma.
fuente
Abuso de excepción
en caso de que se prohíban los literales de cadena / caracteres, puede usar un bloque try catch:
ahora
str
es igual"something"
Si se necesitan más cadenas, puede encadenarlo con un número (por ejemplo, ceros)
ahora
arr
es igual["something", "foo", "bar", " is not defined"]
fuente
Si está inicializando una variable
1
en cada iteración de un bucle (por ejemplo, restableciendo una variable en un bucle externo para un bucle interno), como el siguiente (de mi respuesta a esta pregunta ):Dado que el resultado de una condición como
j++<=n
es1
siempre que sea verdadera, solo puede asignar la condición directamente a la variable (porque cuando se vuelve falsa, el ciclo dejará de ejecutarse y ya no importará):Por lo general, puede guardar 2 caracteres con este método. Saludos a
@ugoren
la idea en los comentarios a esa respuesta.Para otro ejemplo, también apliqué este truco a mi respuesta aquí con la expresión
w=r=++c<S.length
en mi bucle for externo, guardando un total de 4 caracteres.fuente
Si puede aceptar scripts específicos de Spidermonkey (por ahora), puede usar las funciones de flecha de ECMAScript 6 . En lugar de escribir código como el siguiente.
Puedes acortarlo así.
fuente
Si necesita verificar NaN, no lo use
isNaN(x)
, pero usex!=x
, que es más corto y también funciona.Tenga en cuenta que esto solo funciona si
typeof(x) === "number"
; si es una cadena, por ejemplo,isNaN("string")
devuelvetrue
, pero"string" != "string"
devuelvefalse
. ¡Gracias a Cyoce por señalar esto!fuente
isNaN("string")
devolucionestrue
, mientras que"string"!="string"
devolucionesfalse
(obviamente)if(!x){
, si está detectandoNaN
explícitamente.x
al número, lo+x!=+x
hace equivalente aisNaN(x)
, aún así, 2 caracteres más cortos. Entonces,+"string"!=+"string"
vuelve verdadero.Suma de matrices / producto / cociente
ES5 : 17 bytes
ES6 : 15 bytes
Por supuesto, puede cambiarlo
+
por lo que desee, por ejemplo,*
por producto o/
por cociente.fuente
Use una operación bit a bit para redondear un número hacia cero:
(Fuente: propinas al azar )
La precedencia del operador determina cuál será más corto en su programa.
fuente
n=prompt()|0
.Math.floor
es terriblemente lento ... casi no debería usarse, diría yo.Sugerencia de bucle I
Puede guardar el
1
carácter cuando se repite cambiandoi
la última vez que se usó:Nota: también funciona con
--
(pero modifique el bucle en consecuencia para evitar bucles infinitos)Punta de bucle II
Hay ciertos escenarios en los que puedes guardar un personaje jugando con el operador y los valores incrementales:
Nota: debe prestar atención cuando, por ejemplo
0 to -1
. y9 to 10, 99 to 100
, así que juega hasta que encuentres una manera de salvar al personajefuente
Usar en
^
lugar de!=
o==
cuando se compara con un número enteroReemplazar llamadas a funciones matemáticas incorporadas con expresiones más cortas
fuente
-
lugar de!=
para enteros; Por ejemplo,n!=1?a:b
sería equivalente an-1?a:b
Algo que vale la pena señalar es que puede usar una cadena en lugar de cero en algunos casos para guardar un par de bytes aquí y allá en bucles:
fuente
Muy simple, aun así, nadie lo había mencionado.
Si está utilizando
Math.min()
oMath.max()
puede guardar 6 caracteres haciendo esto:fuente
Redondeo
Sé que
Math.floor()
se han publicado alternativas , pero ¿qué pasa con los demás?Piso:
Redondeo:
Techo:
fuente
0|x+1
simplemente suma 1 si el número del que desea encontrar el techo ya es un número entero. Una alternativa segura (principalmente) es0|x+1-1e9
, pero esto es solo tres bytes más corto.0|x+1-1e-9
?x%1?-~x:x
(9 caracteres) es una mejor alternativa. Sin embargo, al igual que las alternativas de pisos0|x
y~~x
, solo funciona para números positivos.En los casos en que está utilizando el operador ternario para elegir entre dos números , y el condicional es un booleano o un número
1 or 0
, puede realizar operaciones matemáticas en su lugar:Nota: Además de esto, se tendrá que eliminar lo innecesario
0-
,+0
,+-
etc.Nota 2: hay un caso aislado donde
(x) !== (x?1:0)
, comox
debe sertypeof === "number"
para que funcione. Sin embargo, en el caso de(-x)
que funcione bien.Nota 3: en caso de que no encuentre ahorros, simplemente use el primero
(x?y:z)
Anteriormente pensé que el método B nunca podría vencer a A, sin embargo, existen excepciones:
Creé un proyecto github que nos simplifica ( demo jsFiddle )
fuente
void 0
(no es una función, sino una palabra clave) no es un valor, simplemente devuelveundefined
.a
debe ser 1 o 0 para que funcionetl; dr: ¡ Usa las funciones de ES6!
Funciones de flecha
Doc: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/arrow_functions
Ejemplo:
fuente
for
...of
es genial. Incluso más corto quefor each
..in
.b = [s(x) for (x of a)]
.Abusar de literales
La muestra reciente: compruebe si
"c"
es mayúscula o minúscula, no importa si no es letrafuente
String({})
da"[object Object]"
.Cómo comparar un número con la ayuda de cómo los números se convierten en booleanos:
Si va a verificar si algo es igual a un número positivo , puede restar esa cantidad e invertir lo que estaba dentro de los bloques
if
yelse
:Y en caso de que desee comparar con un número negativo (* diferente a
-1
), simplemente necesita sumar este número en lugar de restar.* bueno, seguramente puedes usarlo
x.indexOf(y) + 1
, pero en el caso especial de-1
que tengas la oportunidad de usarlo~x.indexOf(y)
.fuente
Utilice la función no estándar de "cierres de expresiones" de Mozilla para guardar muchos caracteres en un script que solo necesita funcionar en los motores SpiderMonkey / Firefox o Rhino. Por ejemplo,
se convierte
Ver la página de desbordamiento de pila para más trucos.
fuente
->bar
let foo = () => bar;
irónicamente más corto que el código de golf anterior.foo=_=>bar
incluso más corto.Usar en
if(~a.indexOf(b))
lugar deif(a.indexOf(b)!=-1)
fuente
En lugar de escribir
true
puedes usar!0
.fuente
!1
parafalse
.1
fortrue
y0
forfalse
, a menos que realmente necesite los valores literales.Transformando a un booleano :
Nota: Esto cambia
0
,""
,false
,null
,undefined
yNaN
parafalse
(todo lo demás atrue
)fuente