LoginSignup
0
1

More than 3 years have passed since last update.

JavaScriptのthisのスコープについて調べた

Last updated at Posted at 2019-11-05

JavaScriptを勉強していて頻繁に出てくるのがこの「this」だが、
定義する場所によって参照先が違ったりと色々厄介なやつなので勉強がてら調べて見た。
(挙動の確認のためあえてvarを使ってるが基本使わないほうがいい)

関数からの呼び出しの場合

var test = 'nogi';

function myThis(){
  console.log(this);  // Window
  this.test = 'hoge';
}

myThis();
console.log(test);  // hoge

関数から呼び出したthisはグローバルオブジェクトを参照していることがわかる。
つまり、グローバル変数のtestに'hoge'を入れたことで'nogi'が変わってしまった(グローバル汚染)
ただし、ES6から変数の定義にletやconstが使えるようになったので特に気にしなくて問題はなさそう。

let test = 'nogi';

function myThis(){
  console.log(this);  // Window
  this.test = 'hoge';
}

myThis();
console.log(test);  // nogi

メソッドからの呼び出しの場合

var test = 'yamada';

var myobj = {  
  test: 'taro',  
  myThis: function(){
    console.log(this);   // {test: "taro", myThis: ƒ}
    this.test = 'hanako';
  }
};

myobj.myThis();
console.log(myobj.test); // hanako
console.log(test); // yamada

メソッドから呼び出したthisは属してるオブジェクトを参照していることがわかる。
当然グローバルスコープへの影響もない。

var test = 'yamada';

var myobj = {
  test: 'taro',  
  myThis: function(){
    console.log(this);  
    this.test = 'hanako';

    function myThis2(){
      console.log(this.test);  // yamada
    }
    myThis2();
  }
};

myobj.myThis();

メソッド内に関数myThis2を追加した場合の挙動。
メソッドで定義しているが、あくまで関数なので参照先はグローバルスコープになっている。

クラスからの呼び出しの場合


var test = 'yamada';

class myClass{
  constructor(){
    this.test = 'taro';
    console.log(this); // myClass {test: "taro"}
  }

  myThis(){
    console.log(this);  // myClass {test: "taro"}
  }
}

var myobj = new myClass();
myobj.myThis();
console.log(test);  // yamada

クラスで呼び出したthisはプロパティもメソッドも属しているクラスを参照していることがわかる。
この辺はシンプルでわかりやすい。

class myClass{
  constructor(){
    this.test = 'taro';
    console.log(this);
  }

  myThis(){
    console.log(this);

    function myThis2(){
      console.log(this);  // undefined
    }
    myThis2();
  }
}

var myobj = new myClass();
myobj.myThis();

クラス内のメソッド内に関数myThis2を定義した。
何と、thisの参照先がundefinedになってしまった!
詳しいことは今度調べてみよう。。

アロー関数からの呼び出しの場合

var test = 'yamada';

var myobj = {
  test: 'taro',  
  myThis: function(){
    this.test = 'hanako';

    var arrow1 = function (){
      console.log(this.test);  // yamada
    }

    var arrow2 = () =>{
      console.log(this.test);  // hanako
    }

    arrow1();
    arrow2();
  }
};

myobj.myThis();

先ほどのメソッド内に定義されている関数のスコープを確認した時のものにアロー関数を追加したもの。
arrow1は前記した通り、関数なのでグローバルオブジェクトを参照しているが、何とアロー関数の場合はメソッドを呼び出しているオブジェクトを参照している。
同じ関数でも参照先が違うのは注意しておきたい。

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