Как работает следующий JavaScript?
Я понимаю, что это миниатюрный код. Я попытался немного деобфускировать его, но не могу получить четкого представления о том, как он достигает этого эффекта. Я вижу, что он использует строки для какой-то итерации, использования объекта Date, странных манипуляций со строками, математических функций, а затем код печатает сам.
Как можно было бы переписать тот же эффект на минимальном примере?
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
Александр
источник
источник
Ответы:
Предисловие : Я украсил и подробно аннотировал код на http://jsfiddle.net/WZXYr/2/
Рассмотрим самый внешний слой:
eval(z = '...');
Строка кода хранится в переменной
z
. Оператор присваивания возвращает присвоенное значение, поэтому строка кода также передается в качестве аргументаeval
.Строка кода
z
выполняется внутриeval
. Код чрезвычайно тупой, даже после очистки, но, похоже, он:4
.e
,x
иy
для удержания карты состояния. Состояние карты частично является функцией текущей секунды на настенных часах (new Date / 1e3
).p
p += " *#"[index]
чтобы решить, использовать ли пробел, звездочку или хеш-метку, гдеindex
на самом делеe[x++] + e[x++]
(как сказано выше,e
иx
отвечают за состояние карты)" *#"
, есть резервный код, который заполняет выводp
символами изz
. Внутренние символы заполняются персонажами анимации, а внешние символы извлекаются изz
.В конце кода есть вызов
setTimeout(z)
, который асинхронно оценивает строку кодаz
. Этот повторный вызовz
позволяет коду зацикливаться.Простой пример:
Вот супер-простая версия ( http://jsfiddle.net/5QXn8/ ):
eval(z='p="<"+"pre>";for(i=0;i<172;++i)if(i > 62 && i < 67)p+="!---"[~~(new Date/1e2 + i)%4];else p += ("eval(z=\'" + z + "\')")[i];document.body.innerHTML = p;setTimeout(z)')
for
Цикл добавляет каждый символ в выходной строкуp
(строка 172 символов):for(i=0;i<172;++i)
Внутреннее условие определяет, находимся ли мы на персонаже между позициями 62-67, которые являются анимированными персонажами:
if(i > 62 && i < 67)
Если да, то распечатайте со
!---
сдвигом на десятые доли секунды значения настенных часов. Это обеспечивает эффект анимации.p+="!---"[~~(new Date/1e2 + i)%4]
(Вся мерзость вокруг
new Date
действительно только для того, чтобы преобразовать значение даты в число от 0 до 3.)В противном случае, если мы не на анимированном персонаже, выведите индексный
i
символ из строки, определенной как"eval(z='" + z + "')"
То есть кодовая строка,
z
окруженнаяeval('
и')
.Наконец, выведите строку и используйте
setTimeout
для постановки в очередь следующего выполненияz
:document.body.innerHTML = p;setTimeout(z)
Обратите внимание, что мой окончательный результат не совсем правильный - я не учел обратную косую черту в конце - но он все равно должен дать вам довольно хорошее представление о том, как работает эта техника в целом.
источник
Вот аннотированный источник. Ps: я автор;)
function z(){ // will be replaced with eval p = "<" + "pre>"; // use <pre> tag for formatted output for ( // loop though lines y in n = ( // y - the line number "zw24" + // n - the encoded data "l6k4" + // every line holds encoded data "e3t4" + "jnt4" + // string will be concated in build process "qj24" + "xh2 4" + // data after spaces will be ignored but "2kty24" + // … is used to not break block comments "wrt4" + // … which will save some chars "13n24" + "3n9h24" + "3pdxt4" + "1csb 4" + "3iyb6k4" + "3pk724" + "3nmr24" ).split(4) // data will be split by (unused) 4 ){ for ( // loop throug every char in line a in t = parseInt( // numbers are encoded as string n[y], // … with a base of 36 36 ) + ( // large number will be converted to string e = // e - holds the rendered globe x = // x - horizonal position r = [] // r - bitmap flag if pixel is set ) ){ r = !r; // toggle binary flag for ( // look though bitmap states i = 0; t[a] > i; // draw pixel t[a]-times i += .05 ) with (Math) // refer to Math later x -= .05, 0 > cos( // prevent backface visibility o = new Date / 1e3 + // get rotation based on current time x / PI ) && ( e[ // access matrix ~~( // convert float to integer sin(o) * // rotate around y axis sin(.5 + y/7) * 32 // scale up the globe ) + 60 // move to center ] = -~r // store bitmap state in render matrix ) } for ( // loop through columns x = 0; 122 > x; // break after char 122 ) p += " *#"[ // add space, asterisk or hash e[x++] + // … based pixel opacity e[x++] ] || (S = ( // otherwise use the original code "eval(z='" + // inception of missing "eval" statement z .split(B = "\\") // escape \ with \\ .join(B + B) .split(Q = "'") // escape ' with \' .join(B + Q) + Q + // add missing ') ")////////" // add extra chars to fill mapping )[ x / 2 + // get character at current position 61 * y-1 ] ).fontcolor( // colorize outpu /\w/.test(S) && // test for [0-9A-Z] "#03B" // render blue // otherwise pink (default) ); document.body.innerHTML = // render output p += // append new line B + // add backspace "\n"; // add new line } setTimeout(z) // render animation on next frame } z()
источник
Вот еще одна деобфусцированная вручную версия, переносящая всю инициализацию из выражения в собственные операторы:
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)'; p = "<" + "pre>"; n = ["zw2", "l6k", "e3t", "jnt", "qj2", "xh2 x/* =<,m#F^ A W###q. */", "2kty2", "wrt", "13n2", "3n9h2", "3pdxt", "1csb yz/* #K q##H######Am */", "3iyb6k", "3pk72", "3nmr2", ""] for (y in n) { e = []; x = 0; r = true; t = parseInt(n[y], 36) + ""; for (a in t) { r = !r for (i = 0; i < t[a]; i += 0.05) { x -= 0.05; o = new Date / 1e3 + x / Math.PI if (Math.cos(o) < 0) e[~~(32 * Math.sin(o) * Math.sin(0.5 + y / 7)) + 60] = -~r; } for (x = 0; x < 122;) { S = "eval" + "(z='" + z.split(B = "\\").join(B + B).split(Q = "'").join(B + Q) + Q + ")//m1k" p += " *#"[e[x++] + e[x++]] || S[x/2+61*y-1]).fontcolor(/\w/.test(S[x/2+61*y-1]) && "#03B"); } p += B + "\n"; document.body.innerHTML = p; } setTimeout(z)
Вот что происходит:
z
представляет собой многострочную строку, содержащую весь код. Этоeval
изд.z
передаетсяsetTimeout
. Работает какrequestAnimationFrame
иeval
вместе, оценивая его в интервале с максимально возможной скоростью.p
, строковый буфер, в который будет добавлен HTML, иn
массив чисел в кодировке base-36 (соединенных в строку с помощью"4"
, комментарии являются несущественным мусором, который не рассматриваетсяparseInt
).n
кодирует одну строку (n.length == 16
). Сейчас он пронумерован .e
набор переменных, некоторые из которых замаскированы под литерал массива, но затем при использовании преобразуются в числа (x
), логические значения (r
) или строки (t
).t
пронумерована, логическое значение инвертируется приr
каждом повороте. Для разных угловx
и в зависимости от текущего времениnew Date / 1000
(чтобы получилась анимация) массивe
заполняется с помощью некоторых побитовых операторов - с1
whenr
is false и2
s whenr
is true в это время.x=0
до 122 двойными шагами, добавляя одиночные символы вp
.B
будучи обратной косой чертой, строкаS
строится из строки кодаz
путем экранирования обратной косой черты и апострофов, чтобы получить точное представление о том, что она смотрела в исходном коде.e
добавляются и используются для доступа к персонажу из" *#"
, для создания анимированного изображения. Если один из индексов не определен,NaN
индекс преобразуется в неопределенный символ, и вместо этогоS
берется соответствующий символ из строки (проверьте формулуx/2+61*y-1
). Если этот символ должен быть символом слова , он окрашивается по-другому с помощьюfontcolor
метода String .p
, а строка HTML назначается телу документа.Другой пример:
setInterval(z='s=("setInterval(z=\'"+\ z.replace(/[\\\\\']/g,"\\\\$&")+"\')"\ ).match(/.{1,37}/g).join("\\\\\\n");d\ ocument.body.innerHTML=\"<\\pre>"+s.s\ lice(0, 175)+String( + new Date()).fo\ ntcolor("red")+s.slice(188)')
( демонстрация на jsfiddle.net )
В нем есть все необходимое для такой анимации:
setInterval
а такжеDate
для анимацииРеконструкция его собственного кода ( похожего на quine ), здесь:
s = ( "setInterval(z='" // the outer invokation + z.replace(/[\\\']/g,"\\$&") // the escaped version + "\')" ) // the end of the assignment .match(/.{1,37}/g).join("\\\n"); // chunked into lines
Выход через
document.body.innerHTML
и<pre>
элементисточник
Строка со всем кодом оценивается, и тайм-аут делает цикл; Строка хранится в переменной с именем
z
и в середине кода, между комментариями,/*
и*/
есть "Earth ASCII Art". Код анализирует комментарии и изменяет содержимое документа, сохраняя js и обновляя искусство. Сильфон - это просто нарезанный код:p="<pre>"; for(y in n="zw24l6k4e3t4jnt4qj24xh2 x42kty24wrt413n243n9h243pdxt41csb yz43iyb6k43pk7243nmr24".split(4)){ for(a in t = parseInt(n[y],36)+(e=x=r=[])) for(r=!r,i=0;t[a]>i;i+=.05) with(Math) x-= .05,0>cos(o=new Date/1e3+x/PI)&&(e[~~(32*sin(o)*sin(.5+y/7))+60] =-~ r); for(x=0;122>x;) p += " *#"[e[x++]+e[x++\]] || (S=("eval"+"(z=\'"+z.split(B = "\\\\").join(B+B).split(Q="\'").join(B+Q)+Q+")//m1k")[x/2+61*y-1]).fontcolor(/\\w/.test(S)&&"#\03B"); p += B+"\\n" document.body.innerHTML= p }
источник