JavaScript (ECMAScript6), 2 bytes por línea
'\
'[
'\
b\
i\
g'
][
'\
c\
o\
n\
s\
t\
r\
u\
c\
t\
o\
r'
][
'\
c\
a\
l\
l'
](
0,
`\
n\
=\
p\
r\
o\
m\
p\
t\
(\
'\
'\
)\
;\
i\
=\
0\
;\
f\
o\
r\
(\
;\
+\
+\
i\
<\
=\
n\
;\
c\
o\
n\
s\
o\
l\
e\
.\
l\
o\
g\
(\
i\
%\
5\
?\
f\
|\
|\
i\
:\
f\
+\
'\
P\
i\
e\
'\
)\
)\
f\
=\
i\
%\
3\
?\
'\
'\
:\
'\
A\
p\
p\
l\
e\
'\
`)
()
Larga explicación
La forma en que podemos acortar las líneas es transformando el código en una cadena y escapando de los extremos de la línea, esto impondrá un límite de 2bytes por línea.
Entonces se alert(1)
convierte
"\
a\
l\
e\
r\
(\
1\
)"
Pero ahora su código es una cadena, por lo que debemos ejecutar la cadena como código. Sé al menos 4 formas en que puede ejecutar una cadena como código:
- eval (código) . Que toma al menos 5 bytes para llamar
eval(
- setTimeout (código, tiempo de espera) . Las ejecuciones funcionan de forma asíncrona, pero opcionalmente si pasa una cadena, invocará eval internamente.
- Puede aprovechar el DOM y poner su código dentro de un
onclick=""
atributo, pero no pude hacer que la creación del elemento sea breve.
- Invocando al constructor de funciones, la nueva función () analizará su código en una función anónima a la que puede llamar más tarde (usé esto).
Todas las funciones nativas de vida dentro de la ventana de objeto y en JavaScript puede acceder a las propiedades del objeto utilizando la notación de puntos por lo eval()
convierte en window.eval()
, o se puede acceder a las propiedades utilizando el notación de corchetes window['eval']()
. Puede aprovechar esto para dividir el eval
en varias líneas utilizando el método descrito anteriormente. Pero aún tiene que escribir la ventana , un truco es que si no está dentro de un marco, la variable superior también es ventana, por lo que window.eval se convierte en top.eval (3 bytes menos).
w=top
w['eval']
You can shorten the assignment using parenthesis
w=(
top
)
w[
'e\
av\
al'
](
/*string*/
)
Entonces esto hará que el código sea mínimo de 3 bytes. Para hacer el código de 2 bytes, utilicé el new Function(/*string*/);
constructor, pero tuve que ser creativo para acceder a él sin tener que escribirlo.
Primero, el constructor de funciones le permite llamarlo como una función omitiendo la nueva palabra clave, esto reduce 4 bytes, pero también es importante por otra razón. Llamando al constructor como una función todavía devuelve una instancia de esta nos permite convertir new Function(code)
a Function(code)
. Otra cosa importante es que el constructor de funciones tiene un call
método que le permite llamar a cualquier función pero anulando esta referencia, y el constructor de funciones en sí es una función a la que puede llamar un método Function.call(null, code)
.
Todas las funciones nativas son instancias del constructor de funciones, y todos los objetos en javascript tienen una propiedad de constructor . Por lo tanto, puede tener acceso al constructor de funciones en cualquier función nativa como alert.constructor
, y utilizando el método de llamada podemos ejecutar el constructor como una función. Ahora tenemos alert.constructor.call (nulo, código) devuelve una función.
combinando los thechiniques anteriores podemos convertirlo en alert['constructor']['call'](null, code)
Ahora solo necesitamos encontrar una función o método con nombre corto, así que elijo el método big () dentro del constructor de cadenas. Entonces puedo acceder directamente desde una cadena vacía"".big
"".big.constructor.call(null, "code")();
''['big']['constructor']['call'](0,'/* code */')()
Luego rompí todo en 2 bytes
Breve er explicación (TLDR)
Estoy accediendo al nuevo constructor de Función (código) para analizar la cadena en lugar de evaluar (código) . Este constructor está disponible en todas las funciones nativas haciendo anyFunction. constructor , como alert.constructor===Function
. Estoy usando una función / método dentro del String.prototype.big String.prototype.big.constructor.call(null, /*string*/)
Pero accediendo directamente desde un literal de cadena "".big
y lo convertí en notación de corchetes . ""['big']['constructor']['call'](0, CODE)
para poder romperlo usando el \
.