Quines in JavaScript
Because programmers have nothing better to do with their free time, they often amuse themselves by finding clever solutions to difficult logic problems. One such problem is called a "quine," and it goes something like this: write the shortest possible program the prints its own source code.
It would be trivial to just read the file that the program is saved as and output that, but most programmers would consider this to be cheating. With this restriction in place creating quines becomes an interesting challenge that is more complicated than it initially appears.
If you've never tried to create a quine in your favorite programming language, I highly recommend you try it before reading further. There's something magical about figuring out how to do it for the first time. Spend some time tinkering until you solve it, then come back here.
Don't look below this turtle burger if you don't want me to spoil your discovery by telling you how to make a quine.
Here's the first quine I made today, in JavaScript:
s=console.log;r=x=>x.replace(/\\/g,"\\\\").replace(/"/g,"\\\"");u="s(\"s=console.log;r=\"+r+\";u=\\\"\"+r(u)+\"\\\";\"+u);";s("s=console.log;r="+r+";u=\""+r(u)+"\";"+u);
The actual program doesn't have any newlines, but here it is broken up into separate statements with some syntax highlighting to make it easier to read:
s=console.log;
r=x=>x.replace(/\\/g,"\\\\").replace(/"/g,"\\\"");
u="s(\"s=console.log;r=\"+r+\";u=\\\"\"+r(u)+\"\\\";\"+u);";
s("s=console.log;r="+r+";u=\""+r(u)+"\";"+u);
At 170 characters in length this is definitely not the shortest possible, but I think it's not bad for a first attempt. Let's walk through how it works.
The first statement just sets a one letter variable to equal the
function console.log
, so that I don't have to retype it
later. Normally in JavaScript you declare variables with
let
or const
, but you don't actually need to.
It will still run just fine as long as you're not in strict mode.
Line 2 declares an arrow function that takes an argument,
x
, and performs two regular expression find and replace
operations on it. It replaces a single backslash with two backslashes,
and a quotation mark with \"
. This essentially "unescapes"
a string, and will be useful later.
The third line is a complex and ugly string containing a bunch of
escaped quotation marks and backslashes. This is the contents of the
final console.log
as a JavaScript string.
The final line actually calls console.log
, printing the
source code. When the function r
is concatenated onto a
string literal, JavaScript calls the Function.toString()
method on it to coerce it into being a string. This inserts the source
code of r
into the string that is printed. Finally,
r(u)
unescapes the string u
so it is printed
with backslashes exactly as it appears in the source code.
This quine works, but it's still a little long. With a bit more time I managed to shorten it to 130 characters:
r=x=>x.replace(/(["\\])/g,"\\$1");u="console.log(\"r=\"+r+\";u=\\\"\"+r(u)+\"\\\";\"+u)";console.log("r="+r+";u=\""+r(u)+"\";"+u)
Once again, here's a version with newlines and syntax highlighting so it's easier to read:
r=x=>x.replace(/(["\\])/g,"\\$1");
u="console.log(\"r=\"+r+\";u=\\\"\"+r(u)+\"\\\";\"+u)";
console.log("r="+r+";u=\""+r(u)+"\";"+u)
The first line is completely removed from this version, because I
realized it's shorter to just type out console.log
twice.
The function r
is shortened by combining the two
replace()
calls into one, using a more complicated regular
expression that does the same thing as the two previous ones.
Because of these changes u
is shorter, and I removed the
final semicolon from the end because it isn't strictly required.
I thought this was the shortest I could get this quine to be, but after another couple hours of playing with it I was able to cut it all the way down to just 35 characters. Behold the shortest JavaScript quine I could come up with:
r=x=>console.log(`r=${r};r()`);r()
I had a hunch the power of Function.toString()
could be
abused to create a very short quine, and it turned out to be right.
First, r
is declared as an arrow function. Note that it
takes one argument, even though this argument is never used. This is
because r=x=>...
is one character shorter than
r=()=>...
and still just as valid. Because all function
parameters are optional in non-strict JavaScript we don't even need to
pass anything to r
when we call it later.
If an arrow function is only one statement you can omit the curly braces
around the body, so the body of this function is just the
console.log
call. Once again r
is converted
into a string through type coercion, this time by inserting it into a
template literal. At the end of the line r()
is actually
called, causing our output to be printed.
This is the shortest JavaScript quine I could think of. A quick search revealed that some very clever people have come up with even shorter ones, but I think 35 characters is still a pretty good score.
Bonus content: other cool quines
You can make quines in almost any programming language, and even some things that aren't really programming languages.
For example, it's possible to make a quine out of a Lempel-Ziv compressed data stream, the format used to define zip files. This means you can create a zip file that recursively contains an infinite number of copies of itself.
Here's a neat shell script quine:
#!/bin/cat
If you make this script executable and run it, the shebang indicates
that the program it should be run with is cat
. This
obviously just prints the file to the stdout, technically making it a
correct quine.
Finally, here's a quine I wrote in Haskell. It's not very good, but it does work:
module Main where
main = do putStr (s ++ (show s) ++ "\n")
where s = "module Main where\n\nmain = do putStr (s ++ (show s) ++ \"\\n\")\n where s = "