JavaScriptのthisは呼び出す場所や方法によって内容が変化します。記事では、thisの使い方から呼び出すパターンを4種類(関数、メソッド、コンストラクタ、apply・call)を紹介しています。また、混同しやすいthatについても紹介しています。
JavaScriptのthisとは?
JavaScriptのコードで「this」を使うことが多いですが、改めて考えると「this」はどのような意味があるのか知っていますか。また、正しい用法で使うことができていますか。
JavaScriptの「this」とは、あらかじめプログラミング言語で用意されている変数のことです。他の変数との違いは、呼び出される場所や方法によって変数の内容が変わる点です。
基本的には、変数は意図的に値を入れることが多いですが、JavaScriptの「this」は内容が状況によって変化します。そのため、「this」が分かりにくく理解が後回しになりがちです。
今回は、使い方や呼び出すパターンを順番に紹介しますので、ぜひこの機会に理解してください。
JavaScriptでのthisの使い方
この章では、まず、基本的な「thisの書き方」を紹介し、「thisの中身を出力する」ことで基本的な変数の内容を確認します。
thisの書き方
thisは、明示的に値をセットする必要がありません。JavaScriptで「this」と書くだけで使用することができます。そういった意味では、特別な変数だと言えます。
基本的な書き方は次の通りです。
【基本的な書き方】
console.log( this );
上記のコードを書くだけでthisの内容が出力されます。要するに、変数に値をセットする必要がなく、実行する場所や方法によって変数の内容が変化します。
thisの中身を出力する
それでは、JavaScriptのthisにはどのような値が格納されているか実際に出力したログを確認しましょう。
先ほど紹介した基本的なthisの書き方のログ出力で内容を確認します。
【サンプルコード】
console.log( this );
【出力結果】
Window {stop: function, open: function, alert: function…
出力結果を確認すると、「Window」が出力されています。これは、JavaScriptで「Windowオブジェクト」という言われるもので、例えば、HTMLを取得や操作する場合に利用される「window.document」のWindowオブジェクトです。thisに何も値を入れなければ、標準ではWindowオブジェクトが格納されています。
thisに新しく変数を追加する場合は、次の通りです。
【サンプルコード】
this.test = 'これはテストです';
console.log( window.test );
【出力結果】
これはテストで
サンプルコードでは、「this.test」に文字列をセットしています。そして、ログ出力時には、windowオブジェクトの「test」で値を取得することが可能です。
要するに、「this.test」で値をセットするということは、Windowオブジェクトにtestを追加することと同じということです。なぜなら、thisには標準でWindowオブジェクトが格納されているからです。
thisを呼び出すパターン
この章では、thisの呼び出し方によってどのように出力される値が変化するかを紹介します。大きく分けて、「関数」、「メソッド」、「コンストラクタ」、「apply.call」で呼び出す方法を紹介します。
関数で呼び出す
まずは、、JavaScriptの「関数」で呼び出す場合を紹介します。具体的には、thisを出力する関数を定義し、その関数を実行します。次のサンプルコードをご覧ください。
【サンプルコード】
// 関数を定義
function test() {
console.log( this );
}
// 関数を実行
test();
【出力結果】
Window {stop: function, open: function, alert: function…
上記のサンプルコードの「test」関数は、thisを出力するだけの関数です。そのため、出力結果は、先ほど紹介した出力結果と同じ、Winddowオブジェクトが出力されています。
メソッドで呼び出す
次に、JavaScriptの「メソッド」で呼び出す場合を紹介します。はじめに、次のサンプルコードをご覧ください。
【サンプルコード】
var sample = {
test: this,
}
console.log( sample.test );
【出力結果】
Window {stop: function, open: function, alert: function…}
上記のサンプルコードは、thisをセットした変数のみのオブジェクトを作成し出力しています。thisを出力していますので、Windowオブジェクトが出力されています。これは、先ほどから紹介している通りです。
次に、オブジェクトにメソッドを生成し、そのメソッドから呼び出した場合を紹介します。次のサンプルコードをご覧ください。
【サンプルコード】
// 変数にセット
var sampleObject = {
test: '呼ばれています',
// thisを出力するメソッドを定義
sampleFunc: function() {
console.log( this );
}
}
// 実行
sampleObject.sampleFunc();
【出力結果】
Object {test: "呼ばれています", sampleFunc: function}
上記のサンプルコードと先ほど紹介した変数のみをセットしたオブジェクトのサンプルコードの違いは、変数のtestには文字列がセットされている点と、sampleFuncメソッドのなかにthisを出力する処理が定義されている点です。
出力結果を見ると先ほどと結果が異なっています。WidowオブジェクトではなくsampleObjectの内容が出力されています。これは、thisの出力処理をsampleFuncメソッド内に移動することで、thisにはsampleObjectオブジェクトが新しくセットされたためです。
このように、thisは記述する場所によって参照するものが変わるので、セットされているthisの内容も変化します。
コンストラクタで呼び出す
次に、JavaScriptのコンストラクタを定義した場合にthisがどのように利用されているか確認していきます。次のサンプルコードをご覧ください。
【サンプルコード】
// コンストラクタ(引数で値を渡す)
function Sample( text1, text2 ) {
this.text1 = text1;
this.text2 = text2;
}
// インスタンスを生成し変数にセット
var sample = new Sample( 'サンプル1', 'サンプル2' );
console.log( sample );
【出力結果】
Sample {text1: "サンプル1", text2:"サンプル2"}
上記のサンプルコードは、コンストラクタを定義する場合によく見かけるコードです。Sampleオブジェクトを生成するときに引数で値を渡しています。そして、thisを使用して値をSampleオブジェクト内のプロパティの「text1」「text2」にセットしています。
出力結果を確認すると、Sampleオブジェクトが出力されています。そして、Sampleのプロパティの「text1」「text2」にそれぞれ値がセットされています。つまり、コンストラクタのthisはSampleオブジェクトを参照しプロパティの役割があります。先ほど紹介したメソッド内のthisとは内容も役割も変わっていることがわかります。
apply,call呼び出しパターン
呼び出しパターンの最後に、「apply,call」を使った呼び出しパターンを紹介します。「apply,call」は、引数に変更したいオブジェクトをセットすることで、thisの内容を変更することができます。基本的な使い方は次の通りです。
【基本的な使い方】
関数.apply( 変更したいオブジェクト )
関数.call( 変更したいオブジェクト
次に、サンプルコードをご覧ください。
【サンプルコード】
// オブジェクトを定義
var food = {
name: 'パイナップル',
price:500
}
// thisを出力
function showLog() {
console.log( this );
}
// 出力したいfoodオブジェクトをセット
showLog.apply( food );
showLog.call( food );
【出力結果】
{name: "パイナップル", price: 500}
{name: "パイナップル", price: 500}
上記のサンプルコードのshowLog()だけの場合は、Windowオブジェクトが出力されます。そこで、showLog.apply()を利用して、引数にfoodオブジェクトをセットすることでfoodオブジェクトが出力されています。このように、thisの内容がWindowオブジェクトからfoodオブジェクトに変化しています。
なお、applyとcallの違いですが、引数が1つの場合には違いがありませんが、引数を2つセットする場合に違いがあります。
【applyとcallの違い】
関数.apply( オブジェクト, 引数[配列] )
関数.call( オブジェクト, 引数 )
2つ目の引数が、applyは配列ですがcallは配列ではありません。2つ目の引数に配列を渡す場合は、applyを使用しましょう。
thatとの違い
thisと同じような使い方をするものに「that」があります。それでは、thisとthatは具体的に何が違うのでしょうか。
「that」は、JavaScriptができた当初から使われてきた変数です。つまり、ただの変数ということです。そのため、thisのように呼び出し場所によって内容が変化しません。thatを使って変数を定義することで可読性を向上させることができます。
まとめ
最後までお読みいただきありがとうございます。
今回は、thisの使い方を中心に紹介しました。thisは呼び出し場所や方法によって内容が変化しますので分かりにくく後回しになりがちです。そこで、今回紹介した「関数」、「メソッド」、「コンストラクタ」、「apply,call」の呼び出す場合をまず理解した上で他のパターンにも広げていけば効率よく習得することができます。
しっかりと理解した上で、今後はthisの意味や内容を意識してプログラミングを行なってください。