【完全ガイド】JavaScriptのbindとは?初心者にもわかる使い方・応用・注意点を徹底解説!

目次

1. JavaScriptのbindメソッドとは?基本と仕組みを解説

1.1 bindメソッドの概要

bindメソッドは、関数のthisを特定のオブジェクトに固定し、新しい関数を返すメソッドです。

function.bind(thisArg[, arg1, arg2, ...])
  • thisArg: 新しい関数で使用するthisの値。
  • arg1, arg2, ...: 新しい関数に固定する引数(オプション)。

1.2 thisの基本とバインドの必要性

JavaScriptでは、関数の実行コンテキストによってthisの参照先が異なります。bindを使うと、意図しないthisの変更を防ぐことができます。

const user = {
  name: "太郎",
  greet: function() {
    console.log(`こんにちは、${this.name}です!`);
  }
};

const greetFunc = user.greet;
greetFunc(); // thisがuserを参照しないため、エラーまたはundefined

const boundGreet = user.greet.bind(user);
boundGreet(); // こんにちは、太郎です!

1.3 【図解】bindを使う前と後でthisがどう変わるか

実行環境thisの参照
メソッドとして実行this はオブジェクトを指す
変数に代入して実行thisundefined または window を指す
bindを使って固定this はオブジェクトを固定する

1.4 call / apply との違い【表で比較】

メソッドthisの設定引数の渡し方戻り値
bind設定したthisを維持固定した引数をセット可能新しい関数を返す
call設定したthisを適用カンマ区切りで渡す関数を即時実行
apply設定したthisを適用配列で渡す関数を即時実行
function greet(greeting) {
  console.log(`${greeting}, ${this.name}です!`);
}

const user = { name: "花子" };

greet.bind(user, "こんにちは")(); // こんにちは、花子です!
greet.call(user, "こんばんは");   // こんばんは、花子です!
greet.apply(user, ["おはよう"]);  // おはよう、花子です!

1.5 まとめ

  • bindメソッドはthisを固定し、新しい関数を作成する。
  • thisの参照先が意図しないものになる場面で特に有効。
  • bindを使うと、関数のthisを指定したオブジェクトに固定できる。
  • callapplyとは異なり、新しい関数を作成するため、後で実行することが可能。

2. JavaScriptのbindの使い方と基本構文

2.1 bindの基本的な書き方

bindメソッドの基本構文は以下の通りです。

function.bind(thisArg[, arg1, arg2, ...])
  • thisArg: thisとして設定したいオブジェクト
  • arg1, arg2, ...: 事前に渡しておく引数(省略可能)

2.2 bindの基本的な使い方

まず、bindを使わずに関数を実行した場合と、bindを使った場合を比較してみましょう。

bindを使わない場合

const person = {
  name: "太郎",
  greet: function() {
    console.log(`こんにちは、${this.name}です!`);
  }
};

const greetFunc = person.greet;
greetFunc(); // thisがpersonを参照しないため、エラーまたはundefined

bindを使った場合

const boundGreet = person.greet.bind(person);
boundGreet(); // こんにちは、太郎です!

2.3 bindメソッドの引数と戻り値

【例1】bindを使ってthisを固定する

const button = document.getElementById("myButton");

const obj = {
  message: "クリックされました!",
  handleClick: function() {
    console.log(this.message);
  }
};

// bindなし(thisがbuttonを指す)
button.addEventListener("click", obj.handleClick);

// bindあり(thisがobjを指す)
button.addEventListener("click", obj.handleClick.bind(obj));

2.4 【表】bindの引数の扱い方(thisのバインド+引数の部分適用)

メソッドthisの固定引数の事前設定実行タイミング
bind可能可能後で実行
call可能不可能すぐ実行
apply可能不可能すぐ実行

【例2】bindで引数を事前に設定する

function greet(greeting, punctuation) {
  console.log(`${greeting}, ${this.name}${punctuation}`);
}

const person = { name: "太郎" };

const sayHello = greet.bind(person, "こんにちは");
sayHello("!"); // こんにちは, 太郎!

const sayGoodbye = greet.bind(person, "さようなら", "…。");
sayGoodbye(); // さようなら, 太郎…。

2.5 まとめ

  • bindメソッドはthisを固定し、新しい関数を作成する。
  • bindを使用すると、イベントハンドラやコールバック関数のthisを明示的に指定できる。
  • bindthisの固定に加えて、部分適用のように事前に引数を設定することも可能。
  • call / apply とは異なり、新しい関数を返すため、後で実行できるのが特徴。

3. JavaScriptのbindメソッドの実践的な使用例

3.1 thisの明示的な固定

thisが変わるケース

JavaScriptでは、関数がどこでどのように呼ばれるかによってthisの参照先が変わるため、意図しない挙動が起こることがあります。

const person = {
  name: "太郎",
  greet: function() {
    console.log(`こんにちは、${this.name}です!`);
  }
};

const greetFunc = person.greet;
greetFunc(); // thisが意図したオブジェクトを指さないため、エラーまたはundefined

bindを使ってthisを固定

const boundGreet = person.greet.bind(person);
boundGreet(); // こんにちは、太郎です!

3.2 イベントハンドラでの活用

bindなし(thisが変更される例)

const button = document.getElementById("myButton");

const obj = {
  message: "クリックされました!",
  handleClick: function() {
    console.log(this.message);
  }
};

button.addEventListener("click", obj.handleClick); // thisはbuttonを参照し、エラーまたはundefined

bindを使ってthisを固定

button.addEventListener("click", obj.handleClick.bind(obj));
// クリックすると "クリックされました!" が表示される

3.3 部分適用関数の作成

bindを使うと、関数の 一部の引数を固定する(部分適用) こともできます。

bindを使った部分適用の例

function multiply(a, b) {
  return a * b;
}

// a を 2 に固定した関数を作成
const double = multiply.bind(null, 2);

console.log(double(5)); // 10
console.log(double(10)); // 20

3.4 クラス(コンストラクタ)での利用

クラスメソッド内でのthisの問題

class Counter {
  constructor() {
    this.count = 0;
  }

  increment() {
    this.count++;
    console.log(this.count);
  }
}

const counter = new Counter();
const incrementFunc = counter.increment;

incrementFunc(); // thisがCounterを参照せず、エラーまたはundefined

bindを使ってthisを固定

class Counter {
  constructor() {
    this.count = 0;
    this.increment = this.increment.bind(this); // thisを固定
  }

  increment() {
    this.count++;
    console.log(this.count);
  }
}

const counter = new Counter();
const incrementFunc = counter.increment;

incrementFunc(); // 1
incrementFunc(); // 2

3.5 まとめ

  • bindを使うと、関数をどこで呼び出してもthisが正しく設定される。
  • イベントハンドラ でのthisの問題を回避できる。
  • 部分適用関数 を作成し、より柔軟な関数を作れる。
  • クラスのメソッド に適用することで、意図しないthisの変更を防ぐ。

4. JavaScriptのbindメソッドの内部動作を解説

4.1 bindが実際にどのように機能するか

bindメソッドを使用すると、新しい関数オブジェクトが作成され、その関数のthisは指定されたオブジェクトに固定されます。

function greet() {
  console.log(this.name);
}

const person = { name: "太郎" };

const boundGreet = greet.bind(person);
boundGreet(); // 太郎

このコードでは、bindによってthispersonに固定され、新しい関数boundGreetが作成されています。

4.2 bindされた関数のprototypeはどうなる?

通常の関数はprototypeを持ちますが、bindされた関数はprototypeを持たず、新しいオブジェクトとして扱われます。

function Person(name) {
  this.name = name;
}

const BoundPerson = Person.bind(null);

console.log(Person.prototype); // { constructor: ƒ }
console.log(BoundPerson.prototype); // undefined

bindを適用すると、コンストラクタ関数としては使えなくなる

const BoundPerson2 = Person.bind(null);
const p = new BoundPerson2("花子"); // TypeError: BoundPerson2 is not a constructor

4.3 【図解】bindはどのように関数を生成するのか?

操作変更点
bind適用前thisは実行時のコンテキストで決定
bind適用後thisが固定され、新しい関数が生成される
bind適用関数prototypeがなくなるため、コンストラクタとして使えない

4.4 thisのバインディングとクロージャの関係

JavaScriptでは、クロージャを使うことで関数が生成された時点の環境を保持できます。
bindメソッドはこの仕組みを活用して、thisを固定した新しい関数を作成します。

クロージャを使ったbindの再現

function customBind(func, thisArg) {
  return function() {
    return func.apply(thisArg);
  };
}

function greet() {
  console.log(this.name);
}

const person = { name: "太郎" };

const boundGreet = customBind(greet, person);
boundGreet(); // 太郎

4.5 まとめ

  • bindを使うと、新しい関数オブジェクトが作成される。
  • bindされた関数は、元の関数とは異なるため、prototypeを持たない。
  • bindクロージャを活用してthisを固定 した関数を作成する。
  • bindされた関数は、コンストラクタとして使用できない。

5. JavaScriptのbindと他の関数メソッド(call / apply)との比較

5.1 bind / call / apply の違いとは?

bindcallapplyは、すべてthisを変更できるメソッドですが、動作が異なります。

bind / call / apply の違い(表で比較)

メソッドthisの設定引数の渡し方実行タイミング戻り値
bind固定される部分適用可能後で実行新しい関数
call変更可能カンマ区切り即座に実行関数の戻り値
apply変更可能配列で渡す即座に実行関数の戻り値

function greet(greeting) {
  console.log(`${greeting}, ${this.name}`);
}

const person = { name: "太郎" };

// bind(新しい関数を作成)
const boundGreet = greet.bind(person, "こんにちは");
boundGreet(); // こんにちは, 太郎

// call(即時実行)
greet.call(person, "こんばんは"); // こんばんは, 太郎

// apply(即時実行、引数を配列で渡す)
greet.apply(person, ["おはよう"]); // おはよう, 太郎

5.2 bind / call / apply の使い分け

場面使うべきメソッド理由
thisを固定した関数を作成したいbind新しい関数を返す ため、後で実行できる
thisを指定しつつ即座に関数を実行したいcallその場で関数を実行できる
配列で引数を渡して即座に実行したいapplyapply引数を配列で渡せる

【例】Math.maxとapplyを使った例

const numbers = [10, 5, 8, 12, 3];
const maxNumber = Math.max.apply(null, numbers);
console.log(maxNumber); // 12

5.3 まとめ

  • bind新しい関数を作る(即時実行しない)。
  • callthisを指定して即座に実行(引数はカンマ区切り)。
  • applythisを指定して即座に実行(引数は配列で渡す)。
  • bindイベントリスナーやコールバック関数thisを固定するのに便利。
  • call / apply関数をすぐに実行したい場合に使う
  • apply配列のデータを関数に渡す場合に便利Math.max など)。

6. JavaScriptのbindメソッドを使う際の注意点

6.1 bindを多用するとパフォーマンスに影響がある?

bindを使うと新しい関数が生成される

bindを適用するたびに新しい関数オブジェクトが作成されるため、無駄なメモリ消費が発生することがあります。

function greet() {
  console.log(this.name);
}

const person = { name: "太郎" };

// 毎回新しい関数が作られる
const greet1 = greet.bind(person);
const greet2 = greet.bind(person);

console.log(greet1 === greet2); // false(異なる関数)

対策:bindした関数をキャッシュする

const boundGreet = greet.bind(person);
boundGreet(); // 再利用可能

6.2 コンストラクタ関数との組み合わせ

bindを適用した関数はnew演算子と相性が悪い

function Person(name) {
  this.name = name;
}

const BoundPerson = Person.bind(null);

const p = new BoundPerson("花子"); // TypeError: BoundPerson is not a constructor

対策:bindを使わずにthisを明示的にセットする

function Person(name) {
  if (!(this instanceof Person)) {
    return new Person(name);
  }
  this.name = name;
}

const p1 = new Person("花子");
const p2 = Person("太郎");

console.log(p1.name); // 花子
console.log(p2.name); // 太郎

6.3 イベントリスナーの削除が難しくなる

bindを使うとremoveEventListenerで削除できない

const button = document.getElementById("myButton");

const obj = {
  message: "クリックされました!",
  handleClick: function() {
    console.log(this.message);
  }
};

button.addEventListener("click", obj.handleClick.bind(obj));
button.removeEventListener("click", obj.handleClick.bind(obj)); // 削除できない

対策:bindした関数を変数に保存する

const boundHandleClick = obj.handleClick.bind(obj);

button.addEventListener("click", boundHandleClick);
button.removeEventListener("click", boundHandleClick); // 正しく削除できる

6.4 まとめ

  • bindは毎回新しい関数を生成するため、多用するとメモリ消費が増える。
  • 対策:事前にbindした関数をキャッシュして再利用する。
  • コンストラクタ関数にbindを適用すると、newでのインスタンス生成ができなくなる。
  • 対策thisを適切に管理し、newが不要な場合は自動的に適用する。
  • bindを使うと、removeEventListenerで削除が難しくなる。
  • 対策:事前にbindした関数を変数に保存し、addEventListenerremoveEventListenerで同じ関数を使う。

7. JavaScriptのbindメソッドに関するFAQ

7.1 bindメソッドはどのような場面で使用すべきか?

bindは、特に 関数のthisが意図しないオブジェクトを指す 場面で活用されます。

bindが役立つ場面

  1. オブジェクトのメソッドを変数に代入するとthisが変わる const user = { name: "太郎", greet: function() { console.log(`こんにちは、${this.name}です!`); } }; const greetFunc = user.greet; greetFunc(); // thisがuserを参照しないためエラー const boundGreet = user.greet.bind(user); boundGreet(); // こんにちは、太郎です!
  2. イベントハンドラでのthisの固定 const button = document.getElementById("myButton"); const obj = { message: "クリックされました!", handleClick: function() { console.log(this.message); } }; button.addEventListener("click", obj.handleClick.bind(obj));
  3. 関数の引数を事前に設定する(部分適用) function multiply(a, b) { return a * b; } const double = multiply.bind(null, 2); console.log(double(5)); // 10

7.2 bindcallapplyの違いは?

メソッドthisの設定引数の渡し方実行タイミング
bind固定される部分適用可能後で実行
call変更可能カンマ区切り即座に実行
apply変更可能配列で渡す即座に実行

function greet(greeting) {
  console.log(`${greeting}, ${this.name}`);
}

const person = { name: "太郎" };

greet.bind(person, "こんにちは")();  // こんにちは, 太郎
greet.call(person, "こんばんは");   // こんばんは, 太郎
greet.apply(person, ["おはよう"]);  // おはよう, 太郎

7.3 bindを使うとメモリリークが起こる?

通常、bind自体がメモリリークの直接的な原因にはなりませんが、bindを多用すると不要な関数オブジェクトが増え、メモリ消費が増加 する可能性があります。

❌ bindを多用すると問題が起こる例

function greet() {
  console.log(this.name);
}

const person = { name: "太郎" };

const greet1 = greet.bind(person);
const greet2 = greet.bind(person);

console.log(greet1 === greet2); // false(毎回新しい関数が生成される)

✅ 対策:bindした関数をキャッシュして再利用

const boundGreet = greet.bind(person);
boundGreet();

7.4 bindとアロー関数はどちらを使うべきか?

アロー関数(=>)は thisを外側のスコープから継承 するため、
場合によってはbindを使わなくてもthisを固定できます。

bindを使わずにthisを固定する方法

const obj = {
  message: "こんにちは!",
  greet: () => {
    console.log(this.message); // `this` は obj ではなく `window` を指す
  }
};

obj.greet(); // undefined

bindが不要なケース(アロー関数を使う)

const button = document.getElementById("myButton");

button.addEventListener("click", () => {
  console.log("クリックされました!");
});

7.5 まとめ

  • bindthisを固定したいときに便利(イベントハンドラ、コールバック関数など)。
  • bind / call / applythisを変更するが、実行タイミングと引数の渡し方が異なる
  • bindの多用はメモリリークを引き起こす可能性があるため、適切にキャッシュを利用する
  • アロー関数はthisを継承するため、bindを使わなくても固定できる場合がある

8. まとめ

8.1 JavaScriptのbindメソッドのポイント

  • bindは、関数のthisを特定のオブジェクトに固定する メソッド。
  • bindを適用すると、新しい関数 が作成される(元の関数は変更されない)。
  • bindを使うと、イベントハンドラやコールバック関数内でのthisの参照先を適切に管理 できる。
  • bind部分適用(関数の一部の引数を固定)にも使える。

8.2 bindが有効な場面と適切な活用方法

場面bindを使う理由
オブジェクトのメソッドを変数に代入する変数に代入するとthisが失われるが、bindで固定できる
イベントハンドラのthisを固定するaddEventListener内のthisはデフォルトで要素を指すため、bindを使ってオブジェクトを参照させる
部分適用関数を作る一部の引数を事前に固定し、再利用しやすい関数を作成できる
非同期処理のコールバック関数非同期関数の内部でthisを維持する

具体例

const obj = {
  message: "こんにちは!",
  showMessage: function() {
    console.log(this.message);
  }
};

const show = obj.showMessage.bind(obj);
show(); // こんにちは!

8.3 bind / call / apply の使い分け

メソッドthisの設定引数の渡し方実行タイミング
bind固定される部分適用可能後で実行
call変更可能カンマ区切り即座に実行
apply変更可能配列で渡す即座に実行

簡単な例

function greet(greeting) {
  console.log(`${greeting}, ${this.name}`);
}

const person = { name: "太郎" };

greet.bind(person, "こんにちは")();  // bind: こんにちは, 太郎
greet.call(person, "こんばんは");   // call: こんばんは, 太郎
greet.apply(person, ["おはよう"]);  // apply: おはよう, 太郎

8.4 bindを使う際の注意点と対策

bindを多用するとメモリ消費が増える

  • 問題bindを適用するたびに新しい関数が作成される。
  • 対策事前にbindした関数をキャッシュ し、再利用する。
const boundGreet = greet.bind(person);
boundGreet(); // 再利用可能

bindを適用した関数はコンストラクタとして使用できない

  • 問題bindするとprototypeがなくなるため、newでのインスタンス生成ができない。
  • 対策bindを使わず、関数内でthisを適切に管理 する。
function Person(name) {
  if (!(this instanceof Person)) {
    return new Person(name);
  }
  this.name = name;
}

bindを使うとremoveEventListenerで削除できない

  • 問題bindを適用すると、毎回異なる関数が生成されるため、removeEventListenerで削除できない。
  • 対策bindした関数を変数に保存 し、addEventListenerremoveEventListenerの両方で同じ関数を使用する。
const boundHandleClick = obj.handleClick.bind(obj);

button.addEventListener("click", boundHandleClick);
button.removeEventListener("click", boundHandleClick); // 正しく削除できる

8.5 まとめ

bindメソッドは関数のthisを固定し、新しい関数を作成する。
bindを使うと、thisの変更を防ぎ、コールバック関数やイベントハンドラでの不具合を解消できる。
bindcallapplyとは異なり、関数を即座に実行せず、新しい関数を返す。
bindを使いすぎるとメモリ消費が増えるため、適切にキャッシュする。
bindを使うとremoveEventListenerで削除できなくなるため、変数に格納して管理する。

広告