どうも!chuckです。
引き続きUnderscore.jsのコードを読んでいきます。
ちなみに、現在100行まで読んだようです。ただし全部で1600行あるので先は長いですね…。
バージョン情報のセット
まず見るのはこの記述。
すごくシンプルな処理ですが、アンダースコアオブジェクトにバージョン情報をセットしています。
ファイル内検索したところ、特に使っている様子は無かったです。
最適化コールバック関数
急に来ました。すごく難しそうな関数。
まず、コメントを翻訳してみます。
Internal function that returns an efficient (for current engines) version of the passed-in callback, to be repeatedly applied in other Underscore functions.
渡されたコーツバックの(現在のエンジンでの)効率的なやつを返す内部関数 。他の関数でも繰り返し適用される。
ふむ、わからんw
分解してみる
まず引数を見てみます。
引数は3つ。名前から察するに「関数、コンテキスト、引数の数」っぽいですね。
処理を見ていきます。
まずこれ。
contextが、void 0 だったら…???謎です。
voidってあれですよね。Javaで言うと返り値がないやつ。JavaScriptにもあったんですね!
ググった。
ん?なんか不穏ですねw
解説はこんな感じ。
void
演算子は与えられた式 (expression) を評価し、undefined
を返します。
用途的には、
この演算子は、「戻り値が
undefined
であってほしい場所に、それ以外の戻り値を持つ式を挿入したい場合」に有用です。
とのこと。
解説の下の方にこんな文章が。
void
演算子は単にプリミティブ値 undefined を得る目的でしばしば使われ、一般的に "void(0)
" と書かれます(これは "void 0
" と等価です)。
要は、undefinedをリテラルで書かない場合に使うってこと?
使ってみる!
testという変数に'test'をセット。その後、void(0)で上書きしてみます。
おっ。
たしかに、undefinedに上書きされています。
話をUnderscore.jsに戻します。
つまり、この条件文は、引数のcontextがundefinedだったときにtrueになるんですね!
そして、引数で渡された関数をそのまま返してますね。
次にこの箇所。
いやあ、なんというか、やばいですね…w
まずswitch文の()の中に三項演算子を使っているの、初めて見ました。
その箇所をズーム。
argCount == null は、あえて等値演算子(==)を使っていますね。たぶん。
「引数にargCountが渡されていなかったら」という処理をしたいと思うんですけど、その場合argCountはundefinedになります。なので、同値演算子(===)を使うとnullとイコールになりません。
でも、ここでなぜ void(0) を使わなかったのか…。うーむ。
いづれにせよ、argCountがなかったらデフォルトで3に設定しているわけですね。
それ以外の場合はargsCountが1か4に設定されるようです。
では、条件文で振り分けられたあとの、swtich文の中身を見ていきます。
argsCountが1だった場合の処理。
valueという引数を取ってfunc.call(context, value)をreturn する、そんな関数をreturnします。…ややこしいですね。
というか、callについて、実はまだよくわかっていません…。
調べた。
概要はこんな感じ。
this の値と、個々にあたえた引数をわたして、関数を呼び出します。
ここでthisArgはこんな役割を持つそう。
- 呼び出し先関数
fun
の中でthis
パラメータとして使用される値です。 実際にこの値が関数の中でthis
の値として使用されるとは限りません: もし、関数が non-strict mode のコードで、null
かundefined
が指定された場合はthis
の値は global object になります。 また、プリミティブ値はボクシングされます。
ちなみにarg1, arg2... は普通の引数。
つまり、contextを関数のthisにセットして、それをreturnしているのがこの処理ですね。
あれ、他の2つの場合も一緒かも。
引数の数が違うだけで、contextをthisにセットしていますね!
そして、これが最後の処理。
if文にもswitch文にも引っかからなかった場合は、この処理に飛ぶようです。
出ました。apply。これも分かったようで分かってないかも…。
また調べた。
thisの値をセットできる点では、まあ同じかな。
callとapplyの違いについては、これがわかりやすかったかも!
なんとなく全体像をつかめた
関数の中身を分解することで、なんとなく全体像がつかめました。
要はcontextが鍵になっていますね。まずif文でcontextがあるか判定して、あればswitch文で分岐させて、contextをthisにセットしています。
だから何?
僕はまだJavaScript中級者未満なので、任意の値をthisにセットするメリットがぱっと浮かびません。
あれですかね?関数の呼び出し方によっては、thisがグローバルオブジェクトを指してしまうので、thisをthatやselfとして確保する必要があるじゃないですか?
そういうことを考えずに済むのかな???
まとめ
ふわーっとですが、処理の流れを追うことが出来ました。
今回はcontext, void, call, applyなど、いかにもJavaScript中級者っぽいワードが出ましたね!call, applyについてはまだ完全に理解したわけではないので、また別で整理できればと思います。