JavaScriptの初見で読みづらいシンタックス&パターン9種

JavaScriptの暗部を感じるカオス

JavaScriptのライブラリを読み解いていると,「お前は何を言っているんだ状態」に陥ることがよくあります.難解なコードを通り越して黒魔術になるとついていけません….

そんなコードリーディングをする中で,初見では意味が分からなかったり,分かりづらかったりした記法をまとめてみます.コードリーディングの一助になりますれば幸い.

eachな感じのループ×2

比較的簡単な類ですが,定石パターンなので一応.色々あると思いますが,自分がよく使う2パターンだけ紹介します.

var elms = [1, 2, 3],
    e,
    i = 0, 

while (e = elms[i++]) {
    // おぅふ
    // i -> 1
}

単純に配列から1個ずつ取り出すだけなら上記のような感じです.

var elms = [1, 2, 3],
    e,
    i = 0,
    iz = elms.length;

for (; i<iz; i++) {
    e = elms[i];
    // おぅふおぅふ
    // i -> 0
}

iが大事ならforを使います.whileの例だと,ループ回るたびにすぐにiがインクリメントされますが,forの例ならブロック内のiはインクリメントされずに残るので.

たとえばi++++iを使い分け始めると,それだけでも結構カオスですよね.基本的にはバッドパターンかもしれんのですが,自分しか手を入れないブツなら使ってしまう感じ.

文字列で呼び出すメソッド・プロパティを指定

これは結構,知った当初は目から鱗でした.理解するとまあ確かにというトコですが.

PHPだと$this->$method()とかやるようなアレと同じですね.

var obj = {};
obj.someFunc = function() { alert('func!'); };

var method = 'someFunc';
obj[method](); // 'func!'

プロパティなら後ろの () を無くすだけです.

この例でメソッド・プロパティという呼び方が常に正しい感じはしませんが,便宜上で.

AND的に〜〜であれば,〜〜する

制御構文使わない分,ちょっとは速いのかな?

var ok = true,
    obj = {};

ok && (obj.prop = 'okらしいから代入するね');

OR的に〜〜でなければ,〜〜する

個人的にはコレのほうがよく使うかも.あるプロパティが未定義であれば,ホニャララを入れるよ,とか.

var obj = {};

obj.prop || (obj.prop = 'undefinedっぽいから代入するね');

否定的反転(?)

自分でコード書くと,なかなか使い所多くないんですが一応.特にuupaa.jsで見かけた記法でした.

var negate,
    ok = true,
    ng = false;

negate = false;

(ok ^ negate); // 1
(ng ^ negate); // 0

negate = true;

(ok ^ negate); // 0
(ng ^ negate); // 1

typeof var === 'undefined'のかわり

undefined周りで,特に読みづらいのはvoidを使ったコレですね.知ってれば読める・知らなければイミフ.

function hoge(arg) {
    if (arg === void 0) {
        // もし,argがundefinedなら
    }
}

このようなundefined絡みの記法は,JavaScript:undefined値の判定 - 泥のようにに多くまとまっていました.

数字になあれ

Numberにキャストされます.ビット演算子すごい.

~~'123'  // 123
~~'0xFF' // 255
~~'1e8'  // 100000000
~~'1+2'  // 0
~~'abc'  // 0

undefinedとかでも0を返す

ビット演算子マジックでUint32(32 ビット符号なし整数)に変換します.

function getLength(maybeAry) {
   return maybeAry.length >>> 0;
}

getLength([1, 2, 3]); // 3
getLength(window);    // 0 (window.lengthとだけ参照するとundefined)

ライブラリじゃありませんが,forEach - MDNとかで見かけました.ループするときに,得体の知れない変数のlengthを参照するときに使うかんじ?

Array#pushのかわり

pushのコストを避けて(?),下記のように書くことがあります.

var elms  = [1, 2, 3], i = 0
    ret = [], j = 0;

while (e = elms[i++]) {
    ret[j++] = e;
}

配列の0から順に埋めて追加していく感じですね.これのためにわざわざlengthみないといけないようなパターンでは,素直にpushしてます.

以上!

今回紹介したのは,一定以上の実用性を伴ったシンタックス&パターンだと思いますが,他にも面白い記法あったら知りたいところ.(紹介させてもらえるとなお嬉しい)

ちなみに自分のコードリーディングは,Textasticが思ったより地味なところで便利ですよ,ビューワーやファイラーとしても素晴らしいで紹介した,Textasticを使っています.iPadをお持ちの方はゼヒ,ソファや布団でごろごろしながら読んでください.