JavaScript is an interesting language. In a conversation in ##javascript on FreeNode, khamer showed me an example of one of the oddities it has:
<khamer> jseval (!![]+[][[]]+[])[+[]]+([]+[][[]])[+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+!+[]+!+[]+!+[]]
<buubot> khamer: Nice
Naturally, I evaluated certain extracts of it, and the way it works is that strings like “undefined” are generated (e.g. by [][+[]]+[]; the concatenation with an empty array implicitly casts it to String), and then indexed to fetch individual letters.
The alphabet “()[]!+” was used in the line by khamer, and by adding “/” one can also get “Infinity”. With this, I could spell out “firefly”. By adding in the object literal “{}”, one can also get the letters in “[object Object]“. The “c” in “Nice” isn’t generated through {}, though, but instead by indexing an array with “filter”, then fetching the c in “function filter() { [native code] }”.
My reply, after a while, was this “firefly” code:
(![]+[])[+[]]+([][![]]+[])[+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+!![]]+(!![]+[])[+[]+!+[]+!+[]+!+[]]+(![]+[])[+[]]+(![]+[])[+[]+!+[]+!+[]]
I just realized one don’t even need the parentheses; (foo) == [foo][0] == [foo][+[]]. This means the minimum alphabet is “[]!+”. With the alphabet “[]!+/{}”, one can get these characters: ” ()INO[]abcdefijlnorstuvy{}/!+”.
The same “firefly” string, without parentheses:
[![]+[]][+[]][+[]]+[[][+[]]+[]][+[]][+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+[]][+[]][+[]+!+[]]+[!+[]+[]][+[]][+[]+!+[]+!+[]+!+[]]+[![]+[]][+[]][+[]]+[![]+[]][+[]][+[]+!+[]+!+[]]+[!+[]/+[]+[]][+[]][+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]
Now I wonder, is it possible to reduce the input alphabet even further, or to generate an even wider range of characters as output?
Edit:
1 2 | N: [[+[]+[[][+[]]][+[]]]+[]][+[]][+[]] u: [[][+[]]+[]][+[]][+[]] |