A JavaScript program that prints itself
The idea is to implement a JS program that prints itself on runtime; console.log
command will be used for output..
-
Initially a program of such kind can have the following view:
s = "<text>"; console.log('s = ' + '<"-symbol>' + s + '<"-symbol>' + s)
The main trick is that<text>
value includes everything after second double quotes symbol:; console.log(...
etc. We can't use double quotes in<text>
value. If we try to escape those, it won't lead us to expected result:<text>
string will include escaped values, but printed output wont't include characters used in escaping. So we can't use double quote charater at any position after enclosing quote ofs="<text>"
and inside<text>
(which is the same sequence of characters). -
The answer is to use unicode escaped characters in strings, " -
\u0022
, ' -\u0027
, \ -\u005c
. This will help us to avoid issue related to nested quotes of the same type. But this don't solve the other problem - output of slash character. -
Let f() be the function that outputs any unicode character from given code. f('0022') -> ", f('005c') -> , etc. The f's body uses eval to process character code.
f = function(a) { return eval('"\\u' + a + '"'); };
-
The program will have the following view:
f = function(a) {...}; s = <text>; console.log('<f-output> s = ' + f('0022') + s + f('0022') + s')
.<f-output> = 'f = function(a) {return eval(' + f('0027') + f('0022') + f('005c') + f('005c') + 'u' + f('0027') + ' + a + ' + f('0027') + f('0022') + f('0027') + ');};'
-
Finally,
<text>
value should be specified.<text> = '; console.log('f = function(a) {return eval(' + f('0027') + f('0022') + f('005c') + f('005c') + 'u' + f('0027') + ' + a + ' + f('0027') + f('0022') + f('0027') + ');}; s = ' + f('0022') + s + f('0022') + s);'
-
Formated text of program. New line characters should be removed.
f = function(a) { return eval('"\\u' + a + '"'); }; s = "; console.log('f = function(a) {return eval(' + f('0027') + f('0022') + f('005c') + f('005c') + 'u' + f('0027') + ' + a + ' + f('0027') + f('0022') + f('0027') + ');}; s = ' + f('0022') + s + f('0022') + s);"; console.log('f = function(a) {return eval(' + f('0027') + f('0022') + f('005c') + f('005c') + 'u' + f('0027') + ' + a + ' + f('0027') + f('0022') + f('0027') + ');}; s = ' + f('0022') + s + f('0022') + s);