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をお持ちの方はゼヒ,ソファや布団でごろごろしながら読んでください.