あけましておめでとうございます。
お正月、いかがお過ごしでしたでしょうか。
おもちは食べましたか。初詣はいきましたか。
さて、たまにはJavaScriptのお話をします。
callとapplyを使うことはありますか。違いは知っていますか。
結論から先に書くと、違いは「引数の渡し方」だけです。
これは別にそんなに重要ではないので、2つのfunctionの使い道をちょっと考えてみます。
何ができるのか
そもそもこれが謎なまま使おうと思っても、使い道は当然ありません。
ためしにMDNのcallの概要を見てみると、
this の値と、個々にあたえた引数をわたして、関数を呼び出します。
とあります。
後半の「個々にあたえた引数をわたして、関数を呼び出します。」は普通の関数呼び出しと変わらないわけですから、
thisの値を渡すことに意味があることがわかります。
つまり、「任意のオブジェクトをthisに束縛できる」というのがcallやapplyの存在意義と言えそうです。
どう使うのか
何ができるのかはわかりましたが、どう使うのかがまだ謎のままです。
というわけで、よく使うパターンを2つほど紹介します。
①イベントバインドされたfunctionを任意のオブジェクトで呼び出す
jQueryなどのライブラリを使うと、イベントに関数をバインドすることが多々あります。
(もちろんネイティブのaddEventListenerとかでも)
$(".target").on("click", myAlert); function myAlert() { alert($(this).text()); }
当然この場合のthisはクリックされた要素自体を指すわけです。
が、myAlertは独立した関数なので、そのまま呼び出すことができます。
$(".newTarget").on("click", function() { myAlert(); myLog(); }); function myAlert() { alert($(this).text()); } function myLog() { console.log($(this).text()); }
この場合、呼び出し時にthisがバインドされていないため、グローバルオブジェクトになってしまいます。
これは困ってしまいますね。そこで、callを使うとこんな風に書き換えることができます。
$(".newTarget").on("click", function() { myAlert.call(this); myLog.call(this); }); function myAlert() { alert($(this).text()); } function myLog() { console.log($(this).text()); }
上の階層のthisを下の階層に渡すことによって、
thisの指す先を示してあげるということですね。
②他オブジェクトのprotetype関数を利用する
こちらはもう少し黒魔術的な使い方です。
よくあるのがargumentsにArrayのprotetype関数を利用するパターンです。
// エラーになる var slicedArgs = arguments.slice(1);
argumentsオブジェクトは配列っぽいのでArrayのprotetype関数を使いたくなりますが、
残念ながら「配列っぽいけど配列じゃない何か」なので使えません。
そこで、callを利用します。
// 使える! var slicedArgs = Array.prototype.slice.call(arguments, 1);
というわけで、可変長引数を利用するとこんなことができるわけですね。
function myConcat(separator) { var slicedArgs = Array.prototype.slice.call(arguments, 1); return slicedArgs.join(separator); } // "first,secont,third"が返る myConcat(",", "first", "second", "third");
個人的にはこの2パターンしかcallやapplyは使いません。
ちょっとややこしいですが、覚えておくと困ったときの解決方法が増えて素敵ですね。
それでは、本年もよろしくお願いします。