タイトルの通り、JavaScriptのcallメソッドについて学んでみました。
以下、MDNからの引用です。
call() はあるオブジェクトに所属する関数やメソッドを、別なオブジェクトに割り当てて呼び出すことができます。
参考:https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/call
これだけだとわかりづらいので、filterメソッドを例を挙げてみます。
filterメソッドは、対象の配列の各要素に対してコールバック関数を実行し、条件を満たす(コールバック関数がtrueを返す)要素だけを抽出した新しい配列を返します。
通常、このfilterメソッドは配列にしか使用できません。
例えば、querySelectorAll() メソッドで取得したNodeListに対して、filterメソッドやmapメソッドなどを使用することはできません。NodeListに対してforEachやlengthは使うことができますが、配列に使用できるメソッドをNodeListに使うことはできないのです。
しかし、callメソッドを利用することで、このNodeListに対しても(少々強引に)filterメソッドを使うことができます。
callメソッドの構文は以下のようなイメージです。
使いたいメソッドを持っているオブジェクト.使いたいメソッド.call(thisの参照先, 使いたいメソッドに渡す引数1, 引数2, 引数3, …)
わかりやすい解説をされている方がいたので、こちらもご紹介させていただきます。
あっちのオブジェクト.あっちのメソッド.call(こっちのオブジェクト, あっちのメソッドに渡す引数);
参考:
https://qiita.com/Chrowa3/items/b3e2961c4930abc1369b
const divs = document.querySelectorAll('div');
// NodeListに対してfilterを使えない場合
const hogeElements = divs.filter(element => element.classList.contains('hoge'));
// NodeListに対してfilterを使える場合
const hogeElements = Array.prototype.filter.call(divs, element => element.classList.contains('hoge'))
つまり、上記の例ではcallメソッドによって、
Arrayオブジェクト内にあるprototypeのfilterメソッドを、NodeList(が代入された変数divs)のメソッドであるかのように扱う
といったことを実現できています。
(prototypeはJavaScript独自の継承の仕組みのことです。こちらについても説明すると長くなるので省略します)
このように、callメソッドを使うことで、あるオブジェクトのメソッドを任意のオブジェクトのメソッドであるかのように利用することができるよ、ということを学びました。