【JavaScript】 thisは本当に単純なものだった
更新日:2024/04/24
JavaScriptでプログラムを組むとき、thisはとても重要なキーワードです。
ですがサンプルコードなどを参考にして、ただなんとなくで使っている人も多いのではないでしょうか。
そこで今回はJavaScriptのthisについて、独断と偏見で解説していきます。
2024/4/24 内容を大幅に見直しました
メソッドのthis
thisは、次のようにオブジェクトのプロパティを、同じオブジェクトのメソッド内で参照するときに使用することが多いです。
thisの例
const obj = {
param1 :"hello!",
param2 :"World!",
hello:function(){
return this.param1 + " " + this.param2;
}
}
console.log( obj.hello() );
実行すると、"hello! World!" とコンソールに出力されます。
上記のコードは、objのhelloメソッド内で、this.param1 と this.param2 を参照しています。
ここでのthis は obj を表すので、"hello!" と "World!" をスペースで連結して返していることになります。
ここで重要なのが、obj.hello() の "." です。
オブジェクトとオブジェクトのメソッドを "." で連結したとき、メソッドにオブジェクトが this値として渡されます。
プロパティアクセスは次のように配列のような記述方法も許されています。
この方法でも、同じようにオブジェクトが this値として渡されます。
obj["hello"]()
特殊な方法を除いてメソッドを実行する方法は上記の二つしかありませんが、
と認識しておく必要があります。
関数のthis値
前項で、「特殊な方法を除いてメソッドを実行する方法は上記の二つしかありません」と書いています。
しかし次のコードは、メソッドを "." または "[ ]" を使用しないで実行しているように見えます。
const obj = {
param1 :"hello!",
param2 :"World!",
hello:function(){
return this.param1 + " " + this.param2;
}
}
const hello = obj.hello;
console.log( hello() );
特殊な方法ではありません。
普通の方法です。
コードを実行すると、次のようにコンソール出力されます。
undefined undefined
this.param1 と this.param2 が undefined になってしまいました。
理由は前項に書いた通り、 "." または "[ ]" を使っていない(実際には使えないが正解)からです。
ちなみに、オブジェクトのプロパティにセットされている関数をメソッドと呼びます。
メソッドを変数に代入したら、その変数は関数です。
"." または "[ ]"を使わないで(実際には使えないが正解)、関数を実行すると thisの値として globalThis がセットされます。
前記コードのhello()メソッドを次のように変更して確認してみます。
hello:function(){
console.log( this === globalThis );
console.log( this );
return this.param1 + " " + this.param2;
}
ブラウザで実行すると、次のような結果になります。
true
thisの値 ▶Window
つまり this値は Windowオブジェクトです。
Windowオブジェクトに、param1とparam2プロパティが存在しないため、アクセスすると undefined が返ります。
そのため、次のような出力結果になったのです。
undefined undefined
なお、thisの値が globalThis になるのは、非strictモードの場合です。
strictモードのときは、undefined になります。
そして undefined はオブジェクトではないので、 undefined.param1 は TypeError になります。
call()、apply()によるthis
"." または "[ ]" を使うと、オブジェクトがメソッドに渡されると書きましたが、call() 、apply() または bind()を使用すると異なる値を this としてメソッドに渡すことができます。
次のコードは、obj.hello() に、obj2をthis値として渡しています。
const obj = {
param1 :"hello!",
param2 :"World!",
hello:function(){
return this.param1 + " " + this.param2;
}
}
const obj2 = {
param1 :"hello!",
param2 :"Taro!",
}
// obj2 を this値として渡す
console.log( obj.hello.call(obj2) );
実行すると、次のように出力されます。
hello! Taro!
"." が二つもあるのに、全く関係ないオブジェクトが渡されました。
次のように関数化したものを実行しても、同じ結果を得ることができます。
const hello = obj.hello;
console.log( hello.call(obj2) );
※プリミティブ値をthis値として渡した場合、非strictモードでは対応するオブジェクトに変換されます。
strictモードでは、そのまま渡されます。
call()とapply()およびbind()については、次のページを参考にしてください。
thisは外部から渡された値
thisは主体となるオブジェクト等の解説がありますが、単純に外部から与えられた値でしかありません。
"." または "[ ]"が記述されていれば直前のオブジェクトが、ただしcall()等を使用すると渡すオブジェクトを変更できます。
どちらでもなければ、globalThis または undefined が渡されます。
そのため、想定外のオブジェクトが渡されることがあります。
ほとんどのケースでは気にする必要がありませんが、重大な問題が予見されるときは対処する必要があるかもしれません。
this独自の制約
thisは外部から与えられたオブジェクトだとお伝えしましたが、実際には他のオブジェクトにない制約があります。
↓↓↓↓
thisは読み込み専用のため、上書きできない。
プロパティの追加や値の変更はできます。
this.prop = 123; // OK
しかしthisそのものに、値をセットすることができません。
this = { x:1 , y:2 }; // SyntaxError: invalid assignment left-hand side
エラーになります。
アロー関数のthis
アロー関数は、thisを持っていません。
渡される渡されない、ではなくて存在自体否定しています。
const func = function(){
console.log( this );
const func1 = function(){
console.log( "関数のthis" , this );
}
func1();
const func2 = ()=>{
console.log( "アロー関数のthis" , this );
}
func2();
}
func.call({value:100});
ブラウザで実行すると、次のように出力されます。
▶Object { value: 100 }
関数のthis ▶Window
アロー関数のthis ▶Object { value: 100 }
通常の関数のthis値が Window なのに対し、アロー関数は外部の this値と同値です。
アロー関数はthisという変数を持っていないので、外部の this が参照されたのです。
アロー関数については次のページを参考にしてみてください。
参考:【JavaScript】 アロー関数は何者!?かっこいいだけじゃない!
更新日:2024/04/24
関連記事
スポンサーリンク
記事の内容について
こんにちはけーちゃんです。
説明するのって難しいですね。
「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。
裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。
掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。
ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php
このサイトは、リンクフリーです。大歓迎です。