みにまむAIのテックブログ

読者です 読者をやめる 読者になる 読者になる

みにまむAIのテックブログ

ブロックチェーンやスマートコントラクトの可能性について考えるブログ。最近では人口知能も視野に入ってきました

JavaScriptの奇々怪々なコードまとめ

f:id:since1991:20170206130818p:plain

JavaScriptって知ってますか?
 
エンジニアの方でなくても、一度は聞いたことがあると思います。JavaScriptは、HTMLやCSSに負けないくらい有名で、世界中の人々に愛されている言語です。stackoverflowの2016年の調査によると、JavaScriptは地球上で最も一般的に使用されているプログラミング言語だそうです。
 
それほどに有名で使用している人が多いが故に、型にはまっていない奇々怪々なJavaScriptコード達が多数存在します。
 
今回はその奇々怪界なコードたちをご紹介していきます。
 

indexOf及び~演算子

まずは入門編。結構よく見かける表現なので、使ったことのある方も多いのではないでしょうか。書きやすい上に知ってる人同士の間ではとってもリーダブルな一品です。
 
 
var foods = ['apple', 'banana', 'orange'];
 
if (~foods.indexOf('apple')) {
    // appleが含まれていた時の処理
}
 
 
これは何をしているのかと言うと、foodsという配列の中にappleという要素が含まれているか否かを判定しています。.indexOf()メソッドは配列内に検索対象が見つかればそのインデックスを、見つからなければ-1を返すため、下記のように判定されることが多いです。
 
 
if (foods.indexOf('apple') !== -1) {
    // appleが含まれていた時の処理
}
 
// 又は
if (foods.indexOf('apple') > -1) {
    // appleが含まれていた時の処理
}
 
 
これだと少し長くなってしまうので、チルダ演算子が登場です。ちなみに、チルダ演算子はビット反転演算子と呼ばれます。
 
 
console.log(~-2); // 1
console.log(~-1); // 0
console.log(~0);  // -1
console.log(~1);  // -2
console.log(~2);  // -3
 
 
ポイントは-1をビット反転させた場合です。-1の時だけ0になっているのがわかると思います。JavaScriptでは0はfalse、それ以外はtrueなので結果的にこのロジックで判定が可能なのです。
 
 

(0, eval)('this')

有名なJavaScriptライブラリ「knockout.js」にて利用されているJavaScriptです。これはJavaScriptのIndirect eval callという仕様を利用したglobalなwindowオブジェクトを取得するためのテクニックです。間接的にevalを実行することで、引数のコードを実行する際のスコープが必ずグローバルになることを利用しています。
 
実際に書いてみると、次のようなコードにてしっかりとwindowオブジェクトを取得出来ています。
 
 
new function() {
    var a = eval('this'); // 直接eval
    var b = (0, eval)('this'); // 間接eval
 
    console.log(a, b); // Object {}, Window {...}
}
 
 
ただしこの仕様、ES5からのようで、ES3環境では下記のようにFunction()を利用する方法のほうがより良いそうです。
 
 
new function() {
    var a = Function('return this')();
 
    console.log(a); // Window {...}
}
 
 
あまり利用するタイミングはなさそうですが、知っておくと周りから「おおー。」と一目置かれる存在になれそうです。
 
 

++[][+]+[+]

おや?と思われた方も多いと思います。これは文字化けではなくれっきとしたJavaScriptのコードです。この式ですが、まず最初に次のように2つのブロックに分解できます。
 
 
++[+]
+
[+]
 
 
次に分解された内の後半部分、[+]は[0]となります。配列は演算対象になった場合、配列自身が持つ.toString()が実行されその後演算処理に渡されるという処理フローを辿ります。よって+はまず.toString()により""に変換され、最終的に+""となり、結果0となります。
 
上記演算によって下記の状態になります。
 
++[0]
+
[0]
 
 
次に++[][0]ですが、[][0]は[]という配列の0番目を参照している式です。[]の0番目、すなわち先頭要素のが返却されます。よって、++[][0]は++[]という演算結果となります。
 
このコードの元ネタは、stackoverflowのJavaScriptカテゴリーにあった質問です。一瞬、「ん?」と思ってしまいますが、実はこの演算には、JavaScriptの理解すべき型変換挙動のエッセンスが詰まっているのです。
 
 
まとめ
いかがでしたでしょうか。私はこの記事を書いていて、改めてJavaScriptの深さを感じました。まだまだ掘るとおもしろい奇々怪界なコードがたくさんあります。今後も引き続き、JavaScriptのリサーチをしていきたいと思います。ここまで読んでくれた皆さん、ありがとうございました。