¿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
whilebucle y luego dividirlo ena,b,cpartes en unforbucle.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()cuesta10personajes. 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
thiso enselflugar dewindowen 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.getElementByIdque se pueden reducir ad[e].Nota:
Con la notación de corchetes, el costo son
6 + name.lengthcaracteres la primera vez. Cada acceso posterior tiene un costo de3caracteres.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
.length4 o más veces en diferentes matrices, puede usar la misma variable que contiene la cadena'length'.fuente
c = ~~a-~~bdebería serc = ~~a+~~b. Además, puede convertir implícitamente a entero usando|0, por ejemploMath.random()*6|0.aybson cadenas, puede hacer+a+bpara convertir a número y agregarlas.d- -balgú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 (
0o1):Si necesita un entero aleatorio
0 <= n < 1337:Esto funciona porque a
Datese almacena internamente en JavaScript como la cantidad de milisegundos desde una época, por lo quenew Datese está coaccionando123somebignumber456cuando 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
ifdeclaraciones 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,
truese 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*jy los operadores de división / módulo recuperan los valores individuales deiyj.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 barEsto 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
Mathporque no tiene un.prototypeatributo. SinMathembargo, 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.localeComparemétodo×, pero eso no debería ser un problema. fuenteConvertir un
whilebucle en unforbucle 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
stres igual"something"Si se necesitan más cadenas, puede encadenarlo con un número (por ejemplo, ceros)
ahora
arres igual["something", "foo", "bar", " is not defined"]fuente
Si está inicializando una variable
1en 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++<=nes1siempre 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
@ugorenla 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.lengthen 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á detectandoNaNexplícitamente.xal número, lo+x!=+xhace 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.floores terriblemente lento ... casi no debería usarse, diría yo.Sugerencia de bucle I
Puede guardar el
1carácter cuando se repite cambiandoila ú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:bsería equivalente an-1?a:bAlgo 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+1simplemente 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|xy~~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), comoxdebe 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.adebe 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...ofes 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
ifyelse: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-1que 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
->barlet foo = () => bar;irónicamente más corto que el código de golf anterior.foo=_=>barincluso más corto.Usar en
if(~a.indexOf(b))lugar deif(a.indexOf(b)!=-1)fuente
En lugar de escribir
truepuedes usar!0.fuente
!1parafalse.1fortruey0forfalse, a menos que realmente necesite los valores literales.Transformando a un booleano :
Nota: Esto cambia
0,"",false,null,undefinedyNaNparafalse(todo lo demás atrue)fuente