Como funciona o seguinte JavaScript?
Eu entendo que é um código reduzido. Tentei desofuscá-lo um pouco, mas não consigo ter um conceito claro de como ele atinge esse efeito. Posso ver que ele está usando Strings para algum tipo de iteração, uso do objeto Date, manipulação de strings estranhas, funções matemáticas e, em seguida, o código se imprime.
Como o mesmo efeito poderia ser reescrito com um exemplo 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
Alexandre
fonte
fonte
Respostas:
Prefácio : Eu embelezei e anotei o código extensivamente em http://jsfiddle.net/WZXYr/2/
Considere a camada mais externa:
Uma string de código é armazenada na variável
z
. O operador de atribuição retorna o valor atribuído, então a string de código também é passada como um argumento paraeval
.A string de código
z
é executada dentro deeval
. O código é extremamente obtuso, mesmo quando limpo, mas parece:4
.e
,x
ey
para manter o estado do mapa. O estado do mapa é, em parte, uma função do segundo atual no relógio de parede (new Date / 1e3
).p
p += " *#"[index]
para decidir se deve usar um espaço, asterisco ou marca de hash, ondeindex
está realmentee[x++] + e[x++]
(como dito acima,e
ex
são responsáveis pelo estado do mapa)" *#"
, haverá um código substituto que preencherá a saídap
com caracteres dez
. Os personagens internos são preenchidos com personagens de animação, enquanto os personagens externos são retiradosz
.No final do código, há uma chamada para
setTimeout(z)
, que avalia de forma assíncrona a string do códigoz
. Essa chamada repetida dez
permite que o código faça um loop.Exemplo simples:
Aqui está uma versão super simples ( http://jsfiddle.net/5QXn8/ ):
O
for
loop adiciona cada caractere à string de saídap
(a string tem 172 caracteres):A condicional interna decide se estamos em um personagem entre as posições 62 a 67, que são os personagens animados:
Se estivermos, imprimamos
!---
, deslocados com base no décimo do segundo valor do relógio de parede. Isso fornece o efeito de animação.(Toda a maldade ao redor
new Date
está realmente lá apenas para transformar um valor de data em um número entre 0 e 3.)Caso contrário, se não estivermos em um personagem animado, imprima o
i
caractere de índice da string definida porOu seja, a string de código
z
cercada poreval('
e')
.Finalmente, imprima a string e use
setTimeout
para enfileirar outra execução dez
:Observe que meu resultado final não está certo - eu não considerei as barras invertidas no final - mas ele ainda deve dar uma boa ideia de como a técnica funciona em geral.
fonte
Aqui está a fonte anotada. Ps: eu sou o autor;)
fonte
Aqui está outra versão desofuscada manualmente, movendo todas as inicializações da expressão para as próprias instruções:
Aqui está o que acontece:
z
é uma string de várias linhas que contém todo o código. Éeval
ed.z
é passado parasetTimeout
. Funciona comorequestAnimationFrame
eeval
igual junto, avaliando-o em um intervalo na maior taxa possível.p
, o buffer de string no qual o HTML será anexado en
uma matriz de números codificados em base 36 (unidos em uma string por"4"
, os comentários sendo lixo irrelevante que não é considerado porparseInt
).n
codifica uma linha (n.length == 16
). Agora está enumerado .e
literal array, mas eles são convertidos em números (x
) ou booleanos (r
) ou strings (t
) quando usados.t
é enumerado, invertendo o booleano ar
cada volta. Para ângulos diferentesx
, e dependendo da hora atualnew Date / 1000
(de modo que dê uma animação), o arraye
é preenchido usando alguns operadores bit a bit - com1
quandor
é falso e2
s quandor
é verdadeiro naquele momento.x=0
até 122 em etapas duplas, acrescentando caracteres únicos ap
.B
sendo a barra invertida, a stringS
é construída a partir da string do códigoz
escapando-se de barras invertidas e apóstrofos, para obter uma representação precisa do que parecia na origem.e
são adicionados e usados para acessar um personagem de" *#"
, para construir a imagem animada. Se um dos índices não for definido, oNaN
índice é resolvido para um caractere indefinido e, em vez disso, o respectivo caractere daS
string é obtido (verifique a fórmulax/2+61*y-1
). Se esse caractere for um caractere de palavra , ele será colorido de forma diferente usando ofontcolor
método String .p
e a string HTML é atribuída ao corpo do documento.Aqui está outro exemplo:
( demonstração em jsfiddle.net )
Ele tem todas as coisas relevantes de que você precisa para este tipo de animação:
setInterval
eDate
para a animaçãoUma reconstrução de seu próprio código ( semelhante a quine ), aqui:
A saída via
document.body.innerHTML
e um<pre>
elementofonte
Uma string com todo o código é avaliada e um tempo limite faz o loop; A string é armazenada em uma variável chamada
z
e no meio do código, entre comentários/*
e*/
há uma "Earth ASCII Art". O código analisa os comentários e altera o conteúdo do documento, mantendo o js e atualizando a arte. Abaixo está apenas o código dividido:fonte