Reverse Engineering a One‑Line JavaScript Animation: Step‑by‑Step Explanation
This article walks through the reverse‑engineering of a compact JavaScript one‑liner that draws a patterned image, refactors it into readable modules, explains each transformation—including variable renaming, loop conversion, ternary expansion, bitwise operations, and switch‑case replacement—while illustrating the underlying math with graphs and code snippets.
The original post links to the article "Reverse Engineering One Line of JavaScript" by Alex Kras and provides the obfuscated one‑liner that renders a patterned image when executed in a browser.
<pre id=p><script>n=setInterval("for(n+=7,i=k,P='p.\\n';i-=1/k;P+=P[i%2?(i%2*j-j+n/k^j)&1:2])j=k/i;p.innerHTML=P",k=64)</script>
To make the code readable, the author moves the JavaScript into a separate code.js file and wraps the <pre> element with id="p" in index.html :
<script src="code.js"></script> <pre id="p"></pre>
In code.js the constant k is renamed to delay and the string passed to setInterval is turned into a real function:
var delay = 64; var draw = "for(n+=7,i=delay,P='p.\\n';i-=1/delay;P+=P[i%2?(i%2*j-j+n/delay^j)&1:2])j=delay/i;p.innerHTML=P"; var n = setInterval(draw, delay);
The author then replaces the eval style string with a proper function body, extracts the DOM element with document.getElementById("p") , and declares the loop variables i , j and p at the top of the function.
var delay = 64; var p = document.getElementById("p"); var draw = function() { var i = delay; var P = 'p.\n'; var j; // ... loop body ... }; var n = setInterval(draw, delay);
The for loop is rewritten as a while loop, keeping only the "check‑every‑loop" part of the original for construct. The ternary expression P += P[i%2?(i%2*j-j+n/delay^j)&1:2] is expanded into explicit if/else logic that determines an index value of 0, 1 or 2.
let index; let iIsOdd = (i % 2 != 0); if (iIsOdd) { index = (i % 2 * j - j + n / delay ^ j) & 1; } else { index = 2; } P += P[index];
The bitwise & 1 is explained as a way to test the least‑significant bit (odd/even). The author then renames the remaining expression to magic and moves the & 1 test into a nested if block.
Next the index handling is replaced by a switch statement, making the three possible characters explicit ( 'p' , '.' , '\n' ).
switch (index) { case 0: P += "p"; break; case 1: P += "."; break; case 2: P += "\n"; break; }
The timer call is simplified to setInterval(draw, 64) because the interval runs only once; the variable n is set to 1 . The constant delay is renamed to DELAY to emphasise its immutability.
The author analyses the mathematics behind the expression (i % 2 * j - j + n / DELAY) ^ j , showing how the XOR operation discards fractional parts (effectively a Math.floor ) and how the parity of the result decides whether a 'p' or '.' is appended.
By substituting j = DELAY / i and simplifying, the expression becomes ((i % 2 * 64 / i - 64 / i) ^ 64 / i) . The article uses Desmos graphs to visualise i % 2 , 64 / i , and their combination, explaining why the first 16 rows of the picture consist mainly of dots (odd results) and later rows contain more 'p' characters (even results).
Finally, the author shows how increasing n by 7 on each timer tick shifts the pattern horizontally, and how after enough ticks the image flips because the XOR result changes parity.
The article concludes that the pattern repeats indefinitely and that understanding each transformation provides insight into JavaScript obfuscation, bitwise arithmetic, and visual rendering.
Hujiang Technology
We focus on the real-world challenges developers face, delivering authentic, practical content and a direct platform for technical networking among developers.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.