🫠

Function.prototype.bindを実装してみた(simple version)

2023/06/18に公開

Zennに同じ内容の文章が見つからなかったので書いてみた

題名通りに、bindを実装する。

あればよい先行知識:

  1. Function.prototype.bindとは何か
  2. Function.prototype.applyの使い方
  3. JSのPrototypeの理解
  4. JSの字句スコープに加えて、Closureの理解
  5. 関数とインスタンスメソッドが呼び出された時、中のthisが参照する先

以上について全くピンと来ない方であれば、軽くZennの他の文章でポイント押さえてから次を読み進めることをお勧めします

Simple Version


Function.prototype.bind = function (context) {
   const funcRef = this // 元の関数への参照に下のclosureが後ほどアクセスできるように
   return function () {
      return funcRef.apply(context, arguments)
   }
}

解説

const funcRef = thisの意図は何か?と思ったら、実際bindされた関数を呼び出す時の状況を例に即して見てみましょう

// bindしたい関数の例
function getName() {
  console.log(this.name)
}
const getNameBinded = getName.bind({name: 'ナナチ'})
getNameBinded() // ナナチ

最後から二行目に、関数たるgetNameがそのインスタンスメソッド.bindを呼び出しているので、問題のthisがここではgetNameを指すことになり、それをfuncRefにキャッシュ。

続いて、closure = getName.bind({name: 'ナナチ'})の実行は、以下のような「結果」をもたらすが

getNameBinded = function () {
  return funcRef.apply(context, arguments)
}

その中、funcRefcontextは、.bind実行時のスコープにあるものを参照していて、参照先の値で置き換えると、つまりこれと同じ、

const getNameBinded = function () {
  return getName.apply({name: 'ナナチ'}, arguments)
}

getNameBinded()を実行するときは... (本文主旨外なので割愛します)


たった六行の短いコードだが、中にはJSの文法の知識がいっぱい詰まってて、個人的には大好物です

最後に、ここまで読んでくださった方がいれば、是非2週間後とかもう一回実装してみましょう!何か新しい発見(おやっ)があるかも

もーちょっと小難しいバージョンもあるが、別の文章で書きたいと思います。

Discussion