記号だけのJavaScriptプログラミングの原理 その2
こんにちは。13日から韓国に来ています。はせがわです。
前回、記号だけのJavaScriptの動作原理を紹介したときは、alert を表示する簡単なコードについて解説しました。
今日は、任意のコードを記号だけで記述する方法について説明します。
前回の方法では、"false","true","[object Object]" という文字列から文字を切り出し、文字列 "alert(1)" を Function コンストラクタに渡して無名関数として実行する、という方法を採りました。
ですので、"alert" 以外の文字を自由に作ることができれば、記号だけで任意のコードを書ける、ということになります。
任意の文字を作り出すということで、最初に思いつくのは String.fromCharCode ですが、記号だけで大文字 C を生成するのはなかなか難しいため、もう少し簡単な方法を考えます。
JavaScriptでは、"\101" のような表記で8進数を使って文字列定数を表現することができますので、これを利用して記号と数値だけで任意の文字を作り出します。
functoin (){
return "\101"; // 文字 'A' を返す関数
}
関数は、前回同様 Number.constructor.constructor すなわち Function コンストラクタを利用し、また "return" という文字は "true" と "undefined" から生成します。これらを組み合わせることで、任意の文字を生成する関数を記号だけで作ることができました。
(0)[ "constructor" ][ "constructor" ] (
(!!{}+"")[ 1 ] + // 'r' : "true"[ 1 ]
(!!{}+"")[ 3 ] + // 'e' : "true"[ 3 ]
(!!{}+"")[ 0 ] + // 't' : "true"[ 0 ]
(!!{}+"")[ 2 ] + // 'u' : "true"[ 0 ]
(!!{}+"")[ 1 ] + // 'r' : "true"[ 1 ]
({}.$+"")[ 1 ] + // 'n' : "undefined"[ 1 ]
"\"" + // '"'
"\\" + // '\'
-~[] + // 1
-[] + // 0
-~[] + // 1
"\"" // '"'
);
8進数で表現できない文字は、\uXXXX という形式で表現します。
$ = +[]; // $ = 0
$ = {
___ : $++, // 0
__$ : $++, // 1
_$_ : $++, // 2
_$$ : $++, // 3
$__ : $++, // 4
$_$ : $++, // 5
$$_ : $++, // 6
$$$ : $++ // 7
};
(0)[ "constructor" ][ "constructor" ] (
(!!{}+"")[ 1 ] + // 'r' : "true"[ 1 ]
(!!{}+"")[ 3 ] + // 'e' : "true"[ 3 ]
(!!{}+"")[ 0 ] + // 't' : "true"[ 0 ]
(!!{}+"")[ 2 ] + // 'u' : "true"[ 0 ]
(!!{}+"")[ 1 ] + // 'r' : "true"[ 1 ]
({}.$+"")[ 1 ] + // 'n' : "undefined"[ 1 ]
"\"" + // '"'
"\\" + // '\'
(!!{}+"")[ 2 ] + // 'u' : "true"[ 0 ]
$._$$ + // 3
$.___ + // 0
$.$__ + // 4
$._$_ + // 2
"\"" // '"'
);
このような方法を利用することで、あらゆる任意の JavaScript を記号だけにすることができました。
実際に、jjencode が生成するJavaScriptを読み解くとより理解が深まると思います。