0
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 3 years have passed since last update.

【JavaScript】関数のthisキーワードについて

Posted at

この記事について

初学者の私にとって、JavaScritpのthisキーワードにかなり混乱してしまうので、
とりあえず関数を中心にthisについてまとめておく。

Thisを関数やメソッドに使うと

メソッド

thisが直感的にわかるメソッドの例から。
メソッドでのthisキーワードは、呼び出し元のオブジェクト(apple)を参照しますね。
なのでapple.priceである150を使用することができます。

method
const apple = {
  price: 150,
  calcPrice: function() {
    this.price * 0.9;
  },
}

apple.calcPrice();

arrow関数

独自のthisキーワードは持たないため、呼び出し元の親スコープがthisとなります。

下記の場合、appleはグローバルオブジェクトで、親がwindowになります。
thisは、windowオブジェクトのpriceプロパティを探そうとするのですが、もちろんwindowオブジェクトにpriceプロパティはないので意図する値は返ってきません。

arrow-function
const apple = {
  price: 150,
  calcPrice: () => console.log(this.price * 0.9),
}

apple.calcPrice();

通常の関数

通常の関数内(function declarationやfunction expression)でのthisキーワードは"undefined"となります。(※strict modeの場合)

注意ポイント

①メソッドでは常に呼び出し元オブジェクトを参照する

下の例にあるように、appleのcalcPriceメソッドをbananaオブジェクトにコピーします。
bananaオブジェクトでは、calcPriceメソッドにあるthisキーワードはappleオブジェクトのpriceか、bananaオブジェクトのpriceのどちらを参照すると思いますか??

答えはbananaオブジェクトです。常に呼び出し元オブジェクトを参照するからです。

copy-method
//appleオブジェクト
const apple = {
  price: 150,
  calcPrice: function() {
    return this.price * 0.9;
  },
}
console.log(apple.calcPrice());  //result -> 135

//bananaオブジェクト
let banana = {
  price: 200,
}

banana.calcPrice = apple.calcPrice;  // apple.calcPriceメソッドをbananaオブジェクトにコピー
console.log(banana.calcPrice());  //result -> 180

②メソッドの中で書かれていても関数ならundefinedとなる

下の例は、メソッドの中に書かれていようが、関数なのでthisはundefinedとなり、下記は正しく動きません。

function-inside-of-method
const apple = {
  price: 150,
  calcPrice: function() {  //calcPriceメソッド
    console.log(1000 - this.price);
    const log = function() {  //log関数
      console.log(this.price);
    }
    log();  //log関数呼び出し
  },
}
apple.calcPrice(); 

ただこちらは回避する方法が二つあります。

解決法①:thisを別の変数に代入しておく。

this-to-self
const apple = {
  price: 150,
  calcPrice: function() {
    console.log(1000 - this.price);
    const self = this; //thisをselfに代入する(appleオブジェクトがselfとなる)
    const log = function() { 
      console.log(self.price); //apple.priceと同じ意味になる
    }
    log();
  },
}
apple.calcPrice(); 

メソッドの中で、thisを別の変数に代入しておけば解決できます。
変数には慣習的にselfや_thisやthatが使われるようですね。

解決法②:arrow関数を使用する

arrow-function
const apple = {
  price: 150,
  calcPrice: function() {
    console.log(1000 - this.price);
    const log = () => { 
      console.log(this.price);
    }
    log();
  },
}
apple.calcPrice(); 

先程も見たようにarrow関数を使用すると、呼び出し元の親スコープがthisとなります。
log()の呼び出し元=calcPriceメソッドで、メソッドはappleオブジェクトを参照するため、thisはapple.priceとなります。

以上です。

0
0
0

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
0
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?