JavaScriptの不可解な挙動たち
はじめに
この記事はKogakuin Univ Advent Calendar 2019 18日目の記事です。 adventar.org
みなさんおはこんばんにちは。どうも、Sugiです。Advent Calenderの記事をかけと言われたものの、書ける && マトモな内容がなかったので、
というタイトルで記事を書くことにしました。 18日に…出せるだろうか…
で、どんな事書くのか
とりあえず、この↓画像をご覧あれ。これは、WebブラウザでF12押すと出てくるアレのConsoleタブでひとつの式を実行した際のスクリーンショットです。

[[][+[]]+[]][+[]][+[]] の返り値が "u" だということを表しているわけです。
は???[と]と+だけでどうやって文字を生成した??そもそもこの式どうなってんだ??
ということで、この式がどうなってんのか、そしてこれに類似した挙動、またそれを利用してこんなこともできるよ(やろうと思えばできるよってだけで、何もいいことないけど)っていうのを解説していこうと、おもんまぁーーーす!!思います。
とりあえず、あの式どうなってんだ
先程の式 [[][+[]]+[]][+[]][+[]] を、[ と ] の対応がわかりやすいようにインデントして行を分けると
[
[]
[
+[]
]
+[]
]
[
+[]
]
[
+[]
]
[ と ] の対応はそれぞれ
1行目 ⇔ 7行目
3行目 ⇔ 5行目
8行目 ⇔ 10行目
11行目 ⇔ 13行目
となっています。
JavaScriptにおいても多くの言語と同じように、[ と ] で囲まれたものは配列であり…というのは、この記事を見ている人たちには解説不要でしょうから省略。というわけで上のコードを見てみると… [ と ] (そろそろこいつら書くの飽きたんでいい略しかた無いかな)で囲まれた部分は、2~6、9、10行目の3つに別れます。2次元配列?? さて、一つめのブロック、2~6行目に関して見ていきましょう。
[]
[
+[]
]
+[]
は????
まぁ分かる人にはわかるんでしょうけども…配列の要素へのアクセスらしく行で書くと、
[][+[]] +[]
うーん…とりあえず、空の配列に添字として +[] をつけてるようです。 +[]とは…?空の配列に+…?そして空の配列の +[] 番目…???
というわけで、2枚目のスクショをどうぞ。

+[] は0として評価されることがわかります。
これはどういうことか…JSにおいて、文字列sに符号として+をつけて+sとするとNumber(s)、-sだと-Number(s)した値が返ってきます。そして文字列ではない値にこれらの符号を付けた場合、これを文字列に変換したもの (配列の他多くのオブジェクトの場合、.toString()でこれが得られる) がsに入ります。
では、[]を文字列に変換すると? 答えから言うと、""(空の文字列) になります。なぜかといえば、配列を文字列に変換すると、以下のような方法で文字列に変換されるからです。(完全なコードではないです><)
function toString(array){
var s = "";
for(var i=0; i < array.length; i++){
s += array[i];
if(i < array.length-1){
s += ",";
}
}
return s;
}
また、4行目において取り出した配列の各要素が文字列ではない場合、その度に文字列に変換されます。もうお気づきだと思いますが、配列が空の場合はfor文が一度も回らないので、空の文字列が返ってきます。
…えーっと、どこまで解説したっけ? あ、+[]の[]が""になるところまで。つまり、+[]は+""と同じであり、これはNumber("")と等価であり、これが0と解釈されるのです。これらを踏まえて、先程の2つめのコードブロックのうち4行目までは、[][0]となります。JSにおいて配列の範囲外参照をするとundefinedが返って来ます。要素数が0の配列の0番目は存在しないので、これもundefinedとなります。では、その後に続く+[]。これはさっきと同じで0だ!…ではなく、それは符号として+や-をつけた時の話で、足し算・引き算の場合(記号の前に何か値がある時)はそうでは有りません。じゃあundefined + []はどうなるのよ?それは[]が文字列に変換されて空文字になり、undefined + ""と等価になります。そしてこれは…文字列になり"undefined"になります。
最初のコードブロックの2~4行目が"undefined"になったので、それを置き換えて1行で書くと ["undefined"][+[]][+[]]となります。何度も言ったように+[]は0になるので、["undefined"][0][0]となります。["undefined"][0]で長さ1の配列["undefined"]から0番目の要素を取り出して"undefined"となるので、それに[0]をつけた["undefined"][0][0]は"undefined"[0]となり、これは"undefined"の0番目の文字、つまり"u"となるのです。
↑この段落長すぎ…
とりあえず謎は解けたね
最初に紹介したコード(?)がどうしてuになるのか、これはわかったかと思います。次は、これを応用してこんな事もできるよ!ってのを紹介していきます。
もっとキモいやつ
ごめんなさい今はここまでしかできてません…近日中に出します!