JavaScriptのbind()メソッドを使いたい

JavaScript&php
ぽんきち
ぽんきち

なんだか関数がうまく動かないにゃ!

勉強中<br>プログラマーさん
勉強中
プログラマーさん

thisの中身って意識してる?

bind()を使った方がいいかも。。。

ぽんきち
ぽんきち

thisはthisじゃないのかにゃ?

訳の分からないこと言わないでほしいにゃ。。。

JavaScriptの挙動が思ったとおりにならない。そんな時にthisが予想外の要素を参照していることがあります。
今回はthisの中身を固定させるbind()メソッドについて解説していきます。




そもそもthisってなに?

まずbind()を理解するには、JavaScript の「this」の働きについて知っておく必要があります。

簡単に言うと:

  • thisは「今、誰がこの関数を呼び出しているか?」を指します。

例:

const user = {
  name: "ぽんきち",
  sayHello: function() {
    console.log("こんにちは、" + this.name + "です!");
  }
};

user.sayHello(); // → こんにちは、ぽんきちです!

ここでのthisuserを意味しておりthis.nameuser.name(=”ぽんきち”)を指します。


でも、thisは変わってしまうことがある。

JavaScriptでは関数を「そのまま」他の場所に渡したりすると、thisの意味が変わってしまうことがあります。

例:

const user = {
  name: "ぽんきち",
  sayHello: function() {
    console.log("こんにちは、" + this.name + "です!");
  }
};

const hello = user.sayHello;
hello(); // → こんにちは、undefinedです!

これはhelloに代入されたseyHelloから見たthisuserを指していないから。
hello()という関数単体として呼び出してしまっているからですね。
(const helloは関数であり、hello自身はnameを持っていないためundefinedになる。)


ここでbind()メソッドの登場

bind()メソッドを使うと、関数の中のthisを固定することができます。

使い方:

const 新しい関数 = 元の関数.bind(thisを固定したいオブジェクト);

使用例:

const user = {
  name: "ぽんきち",
  sayHello: function() {
    console.log("こんにちは、" + this.name + "です!");
  }
};

const hello = user.sayHello.bind(user);
hello(); // → こんにちは、ぽんきちです!

このようにbind()の第一引数にthisを固定したいオブジェクトを指定することで、hello()が呼ばれた時にthisはhello()自身を見ずに、userを見てくれるようになります。

また、既に引数が存在する関数をbind()で固定する場合は、bindの第二引数から順番に引数を渡してあげれば大丈夫です。

例:

const user = {
  name: "ぽんきち",
  greet: function(message, text) {
    console.log(message + ", " + this.name + text);
  }
};

const greetPonkichi = user.greet.bind(user, "こんにちは", "!");

greetPonkichi(); // → こんにちは, ぽんきち!

こんなかんじ。


bind()の応用:イベントハンドラで使う

DOMイベントなどでもthisが意図しないものになることがあります。

const user = {
  name: "ぽんきち",
  handleClick: function() {
    console.log(this.name + "がクリックしました!");
  }
};

const button = document.querySelector("button");
button.addEventListener("click", user.handleClick);

JavaScript では、DOMのaddEventListener()に渡された関数の中のthisはイベントを発生させた要素(今回ならbutton)になるため、ボタンをクリックしてもうまく動きません。(buttonはnameを持っていない)

こんな時もbind()で解決することができます。

const user = {
  name: "ぽんきち",
  handleClick: function() {
    console.log(this.name + "がクリックしました!");
  }
};

const button = document.querySelector("button");
button.addEventListener("click", user.handleClick.bind(user));

// → ぽんきちがクリックしました!

まとめ

  • thisは関数を「誰が呼んだか」で変わる。
  • bind()を使うと関数の中のthisを固定することができる。
  • DOMのイベントハンドラなどでは特に便利。


ちなみにアロー関数はthisを持たないという性質もあるため、場合によってはbindがいらない時もありますが、それはまた別のお話。。。

ぽんきち
ぽんきち

なんとなくわかった気がするから意識して使ってみるにゃァ

勉強中<br>プログラマーさん
勉強中
プログラマーさん

うんうん。

その意気だね。

タイトルとURLをコピーしました