JavaScriptのthisと、bindメソッドについて紹介していきます。JavaやC++に慣れている人にとっては、JavaScriptのthisは少々厄介です(基本的には同じように使えてしまうからです)。この記事では、JavaScriptのthisを使う際の注意事項と、JavaやC++感覚で使えるように(?)するために便利なbindについて説明します。
[topBannar]
this の振る舞い
JavaScriptのthisの仕様は、「ある関数が呼び出された際にその関数を格納していたオブジェクト」を指します。JavaScriptでクラス風のことを実現する場合、クラスのメンバ関数はあるオブジェクトのプロパティに設定されていると思います。例として、以下のような2次元ベクトルのクラスを考えてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// クラス var Vector2D = function(x, y) { // this は生成されたオブジェクト。 this.x = x; this.y = y; }; Vector2D.prototype.getLength = function() { //thisは呼び出し元のオブジェクト return Math.sqrt(this.x * this.x + this.y * this.y); }; var v1 = new Vector2D(10,10); var obj = new Object(); obj.getLength = v1.getLength; console.log(v1.getLength()); console.log(obj.getLength()); |
出力としては、こんな感じの出力になると思います。
1 2 3 4 |
> 14.142135623730951 > NaN |
「v1.getLength()」は、(10, 10)のベクトルの長さを出力してくれますが、「obj.getLength()」では、xやyに値が設定されていないため、長さが計算できず、出力がNaNになってしまいます。この例ではわかりやすいですが、何かの関数にコールバックとして登録した際に、よくわからないことが起こるかもしれません。
bind を使ってthisを束縛
ECMAScript5の仕様に、bindという関数があります。bindを使うことで、thisになるオブジェクトを指定することができます。例えば、先の例を以下のように書き換えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// クラス var Vector2D = function(x, y) { // this は生成されたオブジェクト。 this.x = x; this.y = y; }; Vector2D.prototype.getLength = function() { //thisは呼び出し元のオブジェクト return Math.sqrt(this.x * this.x + this.y * this.y); }; var v1 = new Vector2D(10,10); var obj = new Object(); // !! obj.getLength = v1.getLength.bind(v1); を書き換える obj.getLength = v1.getLength.bind(v1); console.log(v1.getLength()); console.log(obj.getLength()); |
17行目の「v1.getLength」の後ろに「.bind(v1)」が追加されています。このことにより、obj.getLengthには、thisがv1を参照するようなgetLength関数が代入される事になります。このスクリプトを実行すると、以下のように出力されます。
1 2 3 4 |
> 14.142135623730951 > 14.142135623730951 |
bindは、すべての関数オブジェクトの持つ関数です(Function.prototype.bind())。この関数は、第一引数に渡されたオブジェクトがthisになるようなオブジェクトを生成して返してくれます。
[bottomBannar]