この記事について
この記事はJavaScriptのよく分からない言語仕様を楽しく学ぶためのものです
- ある種の縛りコーディングみたいなものです
- ネタなのであまり真剣に扱わないでください(重要)
- 主に、nullだけを使ってJavaScriptでHello, Worldを実現することを目的に講座を進めていきます
- 特に解説とか興味ない方は、一番下のHello, Worldのコードからご覧ください
ルール
この講座で紹介するコードは以下のルールを守ってコーディングされています
- null及び演算子のみで構成されていること
- null以外のリテラル表現(数値、文字列、真偽値、オブジェクト、配列、関数etc)の使用禁止
Lesson1 - 数値を手に入れよう
まずは最も基本的な値である数値をnullから手に入れてみましょう
数値を手に入れる方法はいくつかありますが、例えば
+null // => 0
もしくは、
+!null // => 1
といった方法が存在します
解説
Lesson1のポイントは単項+演算子と論理否定演算子です
特に単項+演算子の挙動は不可解でハマりやすいので気を付けましょう
以下にいくつか例を示しておきます
+"5" // => 5
+"-5" // => -5
+"123asd" // => NaN
+"" // => 0
+true // => 1
+false // => 0
+[] // => 0
+[12] // => 12
+[12, 18] // => NaN
+{} // => NaN
Lesson2 - 文字列を手に入れよう
次はnullから文字列を手に入れましょう
この場合には、typeof演算子を使うことができます
typeof null // => "object"
また任意の文字を手に入れたい場合は、String.fromCharCode()
を使いましょう
(String.fromCharCode()
は文字コードから文字列を生成するための関数です)
まず、String
コンストラクタは以下の方法で手に入れることが可能です
(typeof null).constructor // => function String() { [native code] }
よって、A
を手に入れるコードは以下のようになります
(typeof null).constructor.fromCharCode(
((typeof !null).length + +!null) * ((typeof !null).length + +!null) + +!null
)
// => "A"
補足
Lesson1では単項+演算子を用いた数値の入手方法を紹介しましたが、文字列のlengthプロパティを利用することでさらに柔軟に数値を手に入れることが可能になります
(typeof null).length // => 6
(typeof !null).length // => 7
Lesson3 - 関数を手に入れよう
次は、nullから関数を手に入れましょう
nullから関数を生成するのにはFunction
コンストラクタを利用します
まず、nullからFunction
コンストラクタを手に入れましょう
以下のようにして手に入れることが可能です
(!null).constructor.constructor
ここで少し解説
!null
はtrue
なので、(!null).constructor
はBoolean
コンストラクタ
Boolean
コンストラクタ自体は関数なので、(!null).constructor.constructor
はFunction
コンストラクタを指します
よって、以下のようにして無名関数を生成できます
new (!null).constructor.constructor()
// => function anonymous() {}
さらに、Function
コンストラクタは第一引数に関数の中に記述する処理を文字列として渡すことができます
例えば、こんな感じ
new Function("return null")()
// => null
これを利用して次項ではいよいよHello, Worldを実現していきたいと思います
nullからHello, Worldしよう!!
Lesson1, 2, 3の内容を総動員するとHello, Worldのコードは以下のようになります
実際にデベロッパーツールのコンソールなどで実行して、挙動を確かめてみましょう
new (!null).constructor.constructor(
(typeof null).constructor.fromCharCode(
(typeof !null).length * (typeof !null).length + (typeof !null).length * (typeof !null).length - (+!+null),
(typeof null).length * (typeof null).length * (+!+null + +!+ null + +!+null),
(typeof null).length * (typeof null).length * (+!+null + +!+ null + +!+null) - (typeof !null).length,
(typeof null).length * (typeof null).length * (+!+null + +!+ null + +!+null) + (typeof !null).length - (+!+null),
(typeof null).length * (typeof null).length * (+!+null + +!+ null + +!+null) + (typeof !null).length + (+!+null),
(typeof null).length * (typeof !null).length - (+!+null) - (+!+null),
(typeof null).length * (typeof !null).length - (+!+null) - (+!+null) - (+!+null),
(typeof null).length * (typeof null).length * (+!+null + +!+null),
(typeof null).length * (typeof null).length * (+!+null + +!+ null + +!+null) - (typeof !null).length,
(typeof null).length * (typeof null).length * (+!+null + +!+ null + +!+null),
(typeof null).length * (typeof null).length * (+!+null + +!+ null + +!+null),
(typeof null).length * (typeof null).length * (+!+null + +!+ null + +!+null) + (+!+null + +!+null +!+null),
(typeof null).length * (typeof !null).length + (+!+null) + (+!+null),
((typeof null).length - +!+null - +!+null) * ((typeof !null).length + +!+null),
(typeof null).length * (typeof !null).length * ((+!+null) + (+!+null)) + +!+null + +!+null + +!+null,
(typeof null).length * (typeof null).length * (+!+null + +!+ null + +!+null) + (+!+null + +!+null +!+null),
(typeof null).length * (typeof null).length * (+!+null + +!+ null + +!+null) + (typeof !null).length - (+!+null),
(typeof null).length * (typeof null).length * (+!+null + +!+ null + +!+null),
(typeof !null).length * (typeof !null).length + (typeof !null).length * (typeof !null).length + (+!+null) + (+!+null),
(typeof null).length * (typeof !null).length - (+!+null) - (+!+null) - (+!+null),
(typeof null).length * (typeof !null).length - (+!+null)
)
)()
もう少し最適化できる部分もありますが、とりあえずこんな感じでnullでHello, Worldできますよ、ということでした
(誰得なんだこの記事)
ちなみにこれ、他の言語でもやってみると面白いかも
Rubyのnilとか