¿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
zejecuta dentro deeval. El código es extremadamente obtuso, incluso cuando se limpia, pero parece:4.e,xyyal 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).pp += " *#"[index]para decidir si usar un espacio, asterisco o marca de almohadilla, dondeindexestá realmentee[x++] + e[x++](como se dijo anteriormente,eyxson responsables del estado del mapa)" *#", hay un código de reserva que llena la salidapcon 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 dezpermite que el código se repita .Ejemplo simple:
Aquí hay una versión súper simple ( http://jsfiddle.net/5QXn8/ ):
El
forbucle 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 Dateestá 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
icarácter índice de la cadena definida porEs decir, la cadena de código
zrodeada poreval('y').Finalmente, genere la cadena y úsela
setTimeoutpara 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:
zes una cadena de varias líneas que contiene todo el código. Esevaled.zse pasa asetTimeout. Funciona comorequestAnimationFramey enevalconjunto, 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).ncodifica una línea (n.length == 16). Ahora está enumerado .eliteral de matriz, pero luego se convierten en números (x) o booleanos (r) o cadenas (t) cuando se usan.tse enumera, invirtiendo el booleano enrcada turno. Para diferentes ángulosx, y dependiendo de la hora actualnew Date / 1000(para que dé una animación), la matrizese llena usando algunos operadores bit a bit , con1whenres falso2ys whenres verdadero en ese momento.x=0hasta 122 en pasos dobles, agregando caracteres individuales ap.Bal ser la barra invertida, la cadenaSse construye a partir de la cadena de códigozescapando de las barras invertidas y los apóstrofos, para obtener una representación precisa de lo que se veía en la fuente.ese 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 lugarSse 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 elfontcolormé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:
setIntervalyDatepara la animacionUna reconstrucción de su propio código ( como quine ), aquí:
La salida vía
document.body.innerHTMLy 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
zy 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