¿Cómo funciona el siguiente JavaScript?
Entiendo que es un código minificado. He intentado desenfocarlo un poco, pero no puedo tener una idea clara de cómo logra este efecto. Puedo ver que está usando Strings para iteraciones de algún tipo, uso del objeto Date, manipulación extraña de cadenas, funciones matemáticas, luego el código se imprime solo.
¿Cómo podría reescribirse el mismo efecto con un ejemplo mínimo?
eval(z='p="<"+"pre>"/* ,.oq#+ ,._, */;for(y in n="zw24l6k\
4e3t4jnt4qj24xh2 x/* =<,m#F^ A W###q. */42kty24wrt413n243n\
9h243pdxt41csb yz/* #K q##H######Am */43iyb6k43pk7243nm\
r24".split(4)){/* dP cpq#q##########b, */for(a in t=pars\
eInt(n[y],36)+/* p##@###YG=[#######y */(e=x=r=[]))for\
(r=!r,i=0;t[a/* d#qg `*PWo##q#######D */]>i;i+=.05)wi\
th(Math)x-= /* aem1k.com Q###KWR#### W[ */.05,0>cos(o=\
new Date/1e3/* .Q#########Md#.###OP A@ , */+x/PI)&&(e[~\
~(32*sin(o)*/* , (W#####Xx######.P^ T % */sin(.5+y/7))\
+60] =-~ r);/* #y `^TqW####P###BP */for(x=0;122>\
x;)p+=" *#"/* b. OQ####x#K */[e[x++]+e[x++\
]]||(S=("eval"/* l `X#####D , */+"(z=\'"+z.spl\
it(B = "\\\\")./* G####B" # */join(B+B).split\
(Q="\'").join(B+Q/* VQBP` */)+Q+")//m1k")[x/2\
+61*y-1]).fontcolor/* TP */(/\\w/.test(S)&&"#\
03B");document.body.innerHTML=p+=B+"\\n"}setTimeout(z)')//
javascript
Alejandro
fuente
fuente
Respuestas:
Prólogo : embellecí y anoté el código extensamente en http://jsfiddle.net/WZXYr/2/
Considere la capa más externa:
Una cadena de código se almacena en la variable
z
. El operador de asignación devuelve el valor asignado, por lo que la cadena de código también se pasa como argumento aeval
.La cadena de código se
z
ejecuta dentro deeval
. El código es extremadamente obtuso, incluso cuando se limpia, pero parece:4
.e
,x
yy
al estado de espera mapa. El estado del mapa es, en parte, una función del segundo actual en el reloj de pared (new Date / 1e3
).p
p += " *#"[index]
para decidir si usar un espacio, asterisco o marca de almohadilla, dondeindex
está realmentee[x++] + e[x++]
(como se dijo anteriormente,e
yx
son responsables del estado del mapa)" *#"
, hay un código de reserva que llena la salidap
con caracteres dez
. Los personajes internos se rellenan con personajes de animación, mientras que los personajes externos se extraenz
.Al final del código, hay una llamada a
setTimeout(z)
, que evalúa de forma asincrónica la cadena de códigoz
. Esta repetición de la invocación dez
permite que el código se repita .Ejemplo simple:
Aquí hay una versión súper simple ( http://jsfiddle.net/5QXn8/ ):
El
for
bucle agrega cada carácter a la cadena de salidap
(la cadena tiene 172 caracteres de longitud):El condicional interno decide si estamos en un personaje entre la posición 62 a 67, que son los personajes animados:
Si es así, imprima
!---
, desplazado en función de la décima parte del segundo valor del reloj de pared. Esto proporciona el efecto de animación.(Toda la maldad que hay alrededor
new Date
está realmente ahí para transformar un valor de fecha en un número entre 0 y 3.)De lo contrario, si no estamos en un personaje animado, imprima el
i
carácter índice de la cadena definida porEs decir, la cadena de código
z
rodeada poreval('
y')
.Finalmente, genere la cadena y úsela
setTimeout
para poner en cola otra ejecución dez
:Tenga en cuenta que mi resultado final no es del todo correcto, no he tenido en cuenta las barras invertidas hacia el final, pero aún así debería darle una idea bastante buena de cómo funciona la técnica en general.
fuente
Aquí está la fuente anotada. Ps: soy el autor;)
fuente
Aquí hay otra versión desofuscada manualmente, moviendo toda la inicialización fuera de expresión en declaraciones propias:
Esto es lo que sucede:
z
es una cadena de varias líneas que contiene todo el código. Eseval
ed.z
se pasa asetTimeout
. Funciona comorequestAnimationFrame
y eneval
conjunto, evaluándolo en un intervalo al mayor ritmo posible.p
, el búfer de cadena en el que se agregará el HTML yn
, una matriz de números codificados en base 36 (unidos en una cadena por"4"
, los comentarios son basura irrelevante que no es considerada porparseInt
).n
codifica una línea (n.length == 16
). Ahora está enumerado .e
literal de matriz, pero luego se convierten en números (x
) o booleanos (r
) o cadenas (t
) cuando se usan.t
se enumera, invirtiendo el booleano enr
cada turno. Para diferentes ángulosx
, y dependiendo de la hora actualnew Date / 1000
(para que dé una animación), la matrize
se llena usando algunos operadores bit a bit , con1
whenr
es falso2
ys whenr
es verdadero en ese momento.x=0
hasta 122 en pasos dobles, agregando caracteres individuales ap
.B
al ser la barra invertida, la cadenaS
se construye a partir de la cadena de códigoz
escapando de las barras invertidas y los apóstrofos, para obtener una representación precisa de lo que se veía en la fuente.e
se agregan y se usan para acceder a un personaje de" *#"
, para construir la imagen animada. Si uno de los índices no está definido, elNaN
índice se resuelve en un carácter indefinido y en su lugarS
se toma el carácter respectivo de la cadena (consulte la fórmulax/2+61*y-1
). Si ese carácter debe ser un carácter de palabra , se colorea de manera diferente utilizando elfontcolor
método String .p
, y la cadena HTML se asigna al cuerpo del documento.Aquí hay otro ejemplo:
( demostración en jsfiddle.net )
Tiene todas las cosas relevantes que necesita para este tipo de animación:
setInterval
yDate
para la animacionUna reconstrucción de su propio código ( como quine ), aquí:
La salida vía
document.body.innerHTML
y un<pre>
elementofuente
Se evalúa una cadena con todo el código y un tiempo de espera hace el bucle; La cadena se almacena en una variable nombrada
z
y en el medio del código, entre comentarios/*
y*/
hay un "Arte ASCII de la Tierra". El código analiza los comentarios y cambia el contenido del documento, manteniendo el js y actualizando el art. A continuación se muestra solo el código cortado:fuente