JavaScript で記号プログラミング


# JavaScript で記号プログラミング

JavaScript も他の言語と同様に記号(`$=_-+~[]{}()*/<!\;"',.`)のみを使ったプログラミングが可能です。

以下に console.log("Hello World") を実行するための手順を説明します。

> コードに出てくる **$0** や **$a** などの変数は、読者への説明のために可読性のある形で記述しています。
> もちろん、これらの変数は記号のみを使った形に書き下すことが可能です。


1. まずは記号から数値を導出します。

    ```js
        $0              =  +[];         // 0 (-[] or +"") でも可能
        $1              =  -~[];        // 1
        $2              =  $1+$1;       // 2 (1+1)
        $3              =  $2+$1;       // 3 (2+1)
        $4              =  $3+$1;       // 4 (3+1)
        $5              =  $4+$1;       // 5 (4+1)
        $6              =  $3<<$1;      // 6 (3<<1)
        $7              =  $6+$1;       // 7 (6+1)
        $8              =  $2<<$2;      // 8 (2<<2)
        $9              =  $3*$3;       // 9 (3*3)
        $10             =  $5<<$1;      // 10 (5<<1)
    ```

2. Generic Object( Object,Array,String,Number,RegExp ) の文字列表現から、様々な文字を取得します。

    ```js
        $Object         = ""+{};                        // "[object Object]"
        $false          = ""+![];                       // "false"
        $true           = ""+!![];                      // "true"
        $undefined      = ""+[][[]];                    // "undefined"
        $c              = $Object[$5];
        $n              = $undefined[$1];
        $o              = $Object[$1];
        $r              = $true[$1];
        $s              = $false[$3]
        $t              = $true[$0];
        $u              = $undefined[$0];
        $constructor    = $c + $o + $n + $s + $t + $r + $u + $c + $t + $o + $r;
        $Array          = ""+([][$constructor]);        // "function Array() { [native code] }"
        $String         = ""+(""[$constructor]);        // "function String() { [native code] }"
        $RegExp         = ""+(/ /[$constructor]);       // "function RegExp() { [native code] }"
        $Number         = ""+($0)[$constructor];        // "function Number() { [native code] }"
        $Infinity       = ""+($1/$0);                   // "Infinity"
        $NaN            = ""+(+{});                     // "NaN"
        $a              = $false[$1];
        $b              = $Object[$2];
        $d              = $undefined[$2];
        $e              = $true[$3];
        $f              = $false[$0];
        $g              = $RegExp[$10+$1];
        $i              = $Infinity[$3];
        $j              = $Object[$3];
        $l              = $false[$2];
        $m              = $Number[$10+$1];
        $p              = $RegExp[$10+$4];
        $v              = $RegExp[$10+$10+$5]
        $x              = $RegExp[$10+$3]
        $y              = $Infinity[$7];
        $A              = $Array[$9];
        $E              = $RegExp[$10+$2];
        $I              = $Infinity[$0];
        $N              = $Number[$0];
        $O              = $Object[$8];
        $R              = $RegExp[$9];
        $S              = $String[$9];
    ```

3. new Function を合成します。ここから先は $fn(...) で関数呼び出しが可能になります。

    ```js
        $return         = $r + $e + $t + $u + $r + $n;
        $self           = $s + $e + $l + $f;
        $FunctionObject = ""[$constructor][$constructor]    //  function Function() { [native code] } -> new Function()
        $fn             = $FunctionObject;
    ```

4. Window Object への参照を獲得します。

    ```js
        $WindowObject   = $fn(($return+" "+$self))();       // new Function("return self")() -> [Object Window]
        $Window         = ""+$WindowObject;                 //  "[object Window]"
        $W              = $Window[$8];
        $w              = $Window[$10+$3];
    ```

5. JavaScript の16進表現(\xnn)を使って "h" と "C" を獲得し、String.fromCharCode() の alias **$fnAscii** を合成します。これで任意の文字を獲得可能になりました。

    ```js
        $h              = $fn($return+" '\\"+$x+$6+$8+"'")(); // new Function("return '\x68'")() -> "h"
        $C              = $fn($return+" '\\"+$x+$4+$3+"'")(); // new Function("return '\x43'")() -> "C"
        $fromCharCode   = $S+$t+$r+$i+$n+$g+"."+$f+$r+$o+$m+$C+$h+$a+$r+$C+$o+$d+$e; // "String.fromCharCode"
        $fnAscii        = $fn($n,$return+" "+$fromCharCode+"("+$n+")");
    ```

6. console.log("Hello World") を実行するために不足している "H" と Console Object への参照を獲得し、実行します。

    ```js
        $ConsoleObject  = $WindowObject[$c+$o+$n+$s+$o+$l+$e];
        $fnConsoleLog   = $ConsoleObject[$l+$o+$g];
        $H              = $fnAscii($7*$10+$2)

        $fnConsoleLog($H+$e+$l+$l+$o+" "+$W+$o+$r+$l+$d);   // console.log("Hello World");
    ```

上記のコードを結合するとこうなります。

```js
        $0              =  +[];         // 0 (-[] or +"") でも可能
        $1              =  -~[];        // 1
        $2              =  $1+$1;       // 2 (1+1)
        $3              =  $2+$1;       // 3 (2+1)
        $4              =  $3+$1;       // 4 (3+1)
        $5              =  $4+$1;       // 5 (4+1)
        $6              =  $3<<$1;      // 6 (3<<1)
        $7              =  $6+$1;       // 7 (6+1)
        $8              =  $2<<$2;      // 8 (2<<2)
        $9              =  $3*$3;       // 9 (3*3)
        $10             =  $5<<$1;      // 10 (5<<1)

        $Object         = ""+{};                        // "[object Object]"
        $false          = ""+![];                       // "false"
        $true           = ""+!![];                      // "true"
        $undefined      = ""+[][[]];                    // "undefined"
        $c              = $Object[$5];
        $n              = $undefined[$1];
        $o              = $Object[$1];
        $r              = $true[$1];
        $s              = $false[$3]
        $t              = $true[$0];
        $u              = $undefined[$0];
        $constructor    = $c + $o + $n + $s + $t + $r + $u + $c + $t + $o + $r;
        $Array          = ""+([][$constructor]);        // "function Array() { [native code] }"
        $String         = ""+(""[$constructor]);        // "function String() { [native code] }"
        $RegExp         = ""+(/ /[$constructor]);       // "function RegExp() { [native code] }"
        $Number         = ""+($0)[$constructor];        // "function Number() { [native code] }"
        $Infinity       = ""+($1/$0);                   // "Infinity"
        $NaN            = ""+(+{});                     // "NaN"
        $a              = $false[$1];
        $b              = $Object[$2];
        $d              = $undefined[$2];
        $e              = $true[$3];
        $f              = $false[$0];
        $g              = $RegExp[$10+$1];
        $i              = $Infinity[$3];
        $j              = $Object[$3];
        $l              = $false[$2];
        $m              = $Number[$10+$1];
        $p              = $RegExp[$10+$4];
        $v              = $RegExp[$10+$10+$5]
        $x              = $RegExp[$10+$3]
        $y              = $Infinity[$7];
        $A              = $Array[$9];
        $E              = $RegExp[$10+$2];
        $I              = $Infinity[$0];
        $N              = $Number[$0];
        $O              = $Object[$8];
        $R              = $RegExp[$9];
        $S              = $String[$9];

        $return         = $r + $e + $t + $u + $r + $n;
        $self           = $s + $e + $l + $f;
        $FunctionObject = ""[$constructor][$constructor]    //  function Function() { [native code] } -> new Function()
        $fn             = $FunctionObject;

        $WindowObject   = $fn(($return+" "+$self))();       // new Function("return self")() -> [Object Window]
        $Window         = ""+$WindowObject;                 //  "[object Window]"
        $W              = $Window[$8];
        $w              = $Window[$10+$3];

        $h              = $fn($return+" '\\"+$x+$6+$8+"'")(); // new Function("return '\x68'")() -> "h"
        $C              = $fn($return+" '\\"+$x+$4+$3+"'")(); // new Function("return '\x43'")() -> "C"
        $fromCharCode   = $S+$t+$r+$i+$n+$g+"."+$f+$r+$o+$m+$C+$h+$a+$r+$C+$o+$d+$e; // "String.fromCharCode"
        $fnAscii        = $fn($n,$return+" "+$fromCharCode+"("+$n+")");
        $ConsoleObject  = $WindowObject[$c+$o+$n+$s+$o+$l+$e];
        $fnConsoleLog   = $ConsoleObject[$l+$o+$g];
        $H              = $fnAscii($7*$10+$2)

        $fnConsoleLog($H+$e+$l+$l+$o+" "+$W+$o+$r+$l+$d);   // console.log("Hello World");

```

お疲れ様でした。