1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Javascriptのfunction()とアロー関数でのthis

Last updated at Posted at 2022-09-30

はじめに

普段C#で開発を行っていますが、最近Web開発技術も勉強中です。
その中で、Javascriptのthisで混乱したことがあったので整理します。

Javascriptのthis

例えば、ブラウザのコンソールで以下のコードを書きます。

let user = { 
    firstName: "John",
    sayHi: function(){
        console.log( this.firstName )
    }
 };

この場合、user.sayHi()を実行すると、コンソールで"John"を表示できます。

今度は以下のようにアロー関数内でthisを使ってみます。

let user = {
  firstName: "John",
  func: () => console.log(this.firstName)
};

この場合、user.func()を呼んでもコンソールで"undefined"が表示されました。

thisを確かめるため、以下のコードに書き換えました。

let user = {
  firstName: "John",
  func: () => console.log(this)
};

上記を試すと、コンソールにWindowが表示されました。
アロー関数の場合、thisはWindowを指しますが、WindowはfirstNameを持っていないため、undefinedとなるようです。

function()を使用する場合と、アロー関数を使用する場合で、thisの指し先が異なっています。
MDNには以下の記載がありました。(MDNの該当箇所はこちら)

ほとんどの場合、this の値はどのように関数が呼ばれたかによって決定されます (実行時結合)。これは実行時に代入によって設定することはできず、関数が呼び出されるたびに異なる可能性があります。

アロー関数の場合、MDNには以下の記載がありました。(MDNの該当箇所はこちら)

アロー関数では、this はそれを囲む構文上のコンテキストの this の値が設定されます。グローバルコードでは、グローバルオブジェクトが設定されます。

function()の場合は実行時にthisを決定し、アロー関数の場合は、呼ばれ方に寄らず、常に定義した場所でのthisを参照するという解釈をしました。

実行時の呼ばれ方というのをもう少し詳しく見るため、以下のようなコードを書いた場合を考えます。

let user = { firstName: "John" };
let admin = { firstName: "Admin" };
function sayHi() {
  console.log( firstName.name );
}
user.f = sayHi;
admin.f = sayHi;

sayHi();   // "undefined"が表示される
user.f();  // "John"が表示される
admin.f(); // "Admin"が表示される

どのオブジェクトから呼ばれているかによってthisが変わるということのようです。
オブジェクトに設定せず、コンソール上でただsayHi()を呼ぶ場合、呼び出しているオブジェクトがグローバルコンテキスト(ブラウザ上だとWindow)になり、グローバルでfirstNameプロパティを設定していないため、undefinedとなります。

気になったので以下の場合を試しました。

let user = {
  firstName: "John",
  func: () => alert(this.firstName),
  sayHi: function(){
        this.func();
    }
};

user.sayHi(); // alertで"undefined"が表示される

function()の中のthisはuserを指せているため、alertの表示自体は出ますが、アロー関数のthisは定義時のthisを参照する、つまり、今回の場合はグローバルオブジェクトのWindowを指します。
グローバルオブジェクトでは特にnameプロパティを定義していないため、undefinedが表示されました。

さいごに

thisの扱い方、ややこしかったですが、いろいろ試して整理できました。

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?