LoginSignup
4
7

More than 5 years have passed since last update.

JavaScriptのthisについてまとめてみた

Last updated at Posted at 2019-03-18

this とは

JavaScript(以下JS)のコードを読んでいると、thisがたくさん出てくることあると思います。
JSのコードでthisが出てくると、「このthisって何を指しているのだろうか?」と勉強したての頃はよくなりました。
thisは日本語訳すると「これ」です。代名詞です。
JSになると「この」プロパティを指すか、「この」関数を指すか、このオブジェクトを指すか、thisの前後によって意味が異なります。JSの始めたての人はこのthisでつまずきやすいのでないでしょうか。しかし逆を言うとこのthisを把握することによってコードの理解力が上がると思います。

thisの注意点

上記でも述べましたが、「これ」といってるだけで呼び出した場所や方法によってその中身が変化します。要点を抑えて正しいthisの把握をしていきましょう。
最初に大事なことを言うと、thisの意味を把握するうえでの基準は.(ドット)です。

※最後の方ではドラえもんの例でごり押ししているので、ご了承ください。

thisの使い方

thisの中身はいろいろ変化しますが、だいたいパターンは決まっています。次の5種類くらいです。

  1. グローバルオブジェクト
  2. メソッドチェーン
  3. 関数呼び出し
  4. コンストラクタ呼び出し
  5. callapply

以下、それぞれの種類を説明していきます。

1.グローバルオブジェクト

説明

関数の呼び出しにおいて.がない場合は、グローバル変数的なthisを呼びます。つまりwindowプロパティです。

具体例

function test() {
    console.log(this);
}
test(); //.がない

//結果
//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}

2. メソッドチェーン

説明

関数の呼び出しにおいて.がある場合は、その前のオブジェクトを指します。これは一般的な代名詞使用法です。以下の具体例でいうと【「この」オブジェクトのshow関数を実行します!!】と叫んでいるのが「myObject.show();」です。ここではオブジェクトのthis.name、すなわちmyObjectnameであるmk0812を呼びます。ここまでのthis記法は多分まだ簡単だと思います。

具体例

var myObject = {
    name: 'mk0812',
    show: function(){
        console.log(this.name);
    }
}
myObject.show(); //.がある場合はその前のオブジェクトを指す

//結果
//mk0812

3.関数呼び出し

説明

ここから本番です。関数呼び出しとはメソッドの中で関数を呼ぶことです。言ってることがさっぱりわからないので具体例の中で説明しましょう。

具体例

var myObject = {
    name: 'mk0812',
    show: function(){
        console.log(this.name); //①

        function show(){
            console.log(this.name); //②
        }
        show();
    }
}
myObject.show(); //.がある場合はその前のオブジェクトを指す。がメソッドの中にthisを参照する関数がある。

//結果
//①.. mk0812
//②.. undefined

この場合は、①は2.メソッドチェーン同様にmk0812を指しますが、②のthisundefinedを指します。ここで②のthisはグローバルオブジェクトを呼び出しています。気を付けてほしいのはメソッド内で関数呼び出しになっている場合はthisの中身は引き継がれないことです。そのメソッド内ではshow();と定義されています。このshow();は誰からも定義されていないので、.がない関数呼び出しとしてグローバルオブジェクトを呼び出します。

undefinedはやだ!かわいそう!というのなら、そのthisを別の変数(self)で置き換えて呼びましょう。

var myObject = {
    name: 'mk0812',
    show: function(){
        var self = this;
        console.log(this.name); //①

        function show(){
            console.log(self.name); //②
        }
        show();
    }
}
myObject.show();

//結果
//①.. mk0812
//②.. mk0812

4.コンストラクタ呼び出し

説明

コンストラクタ呼び出しは、newをつけてインスタンスを生成します。
そのインスタンスの中身のthisはインスタンス自身になります。

これはnewをつけるかつけていないかでは、全然違います。
newをつけていない場合はただの関数です。つまりMyObject('mk0812');の場合は関数呼び出しです。グローバル変数のthisnameが定義されます。インスタンスとして呼びたい場合は必ずnewをつけましょう!

具体例

function MyObject(name){
    this.name = name;
    this.add = function(value){
        this.name = this.name + value;
    }
    this.show = function(){
        console.log(this.name);
    }
}

var mk = new MyObject('mk0812');
mk.add('aaa');
mk.show();

//結果
//mk0812aaa

5.callapply

説明

callapplyは「this」を自由に操りたい場合、この方法を用いられます。最初は僕はさっぱりわかりませんでした。僕の勝手なイメージですが、この記法は自作のライブラリとかを作りたい場合、よく使われる印象があります。この「apply」と「call」を使うと「強制的にthisを束縛」できます。僕は「は?束縛?意味わからん」となりました。ここは分かりやすく「ドラえもん」で具体例を出しましょう。

具体例

のび太とジャイアンの関係性でいうと、のび太はジャイアンより弱い設定です(秘密道具を使うとかはなしにしましょう)。のび太が手に入れた漫画はすべてジャイアンのものになります。悲しい世界だ。。。

var nobita = {
    book: 'これはのび太の漫画だよ',
    show: function() {
        console.log(this.book);
    }
};

var jian = {
    book: 'お前のものはおれのもの、おれのものはおれのもの'
}
nobita.show.apply(jian) //'お前のものはおれのもの、おれのものはおれのもの'
nobita.show.call(jian) //'お前のものはおれのもの、おれのものはおれのもの'

「apply」と「call」の第一引数は「this」にsetしたいオブジェクトです。のび太はジャイアンのjianオブジェクトに完全に支配され、bookプロパティが上書きされました。これだけ見ると「apply」と「call」の違いはあまりなさそうですが「apply」と「call」の違いは第二引数以降の取り方です。

var nobita = {
    book: 'のび太の漫画だよ',
    show: function(book1,book2) {
        console.log(book1,book2 + '' + this.book);
    }
};

var jian = {
    book: 'おれのもの'
}
nobita.show.apply(jian,['どら焼きの本','カレーの本']); //どら焼きの本 カレーの本はおれのもの
nobita.show.call(jian,'どら焼きの本','カレーの本'); //どら焼きの本 カレーの本はおれのもの

「apply」は第二引数に配列をとり、配列の中身が引数として渡されます。
「call」はそのまま第二引数以降が引数として渡されます。

その他

bind

bindは強制的にオブジェクトと結びつける関数です。

function nobita(){
    console.log(this);
}

var jian = {
    book: 'おれのもの'
}
var another_jian = nobita.bind(jian);
another_jian();

//結果
//'おれのもの'

関数 another_jian の呼び出しには .がついていませんが、 bindされているので、呼び出し時に jian. が付く形になります。そのためanother_jianthisjian(別のジャイアンもジャイアンとなる)

まとめ

結局、thisってなんだっけ?ドラえもんだっけ?となった方にまとめを書きます。基本的には.を見て判断しましょう。使い方は次の5種類です。

  1. グローバルオブジェクト .. .がない→グローバルオブジェクト
  2. メソッドチェーン .. .がある→.の前のオブジェクトを指す。
  3. 関数呼び出し .. メソッドの中の関数のthisはグローバル
  4. コンストラクタ呼び出し .. newをつけようね
  5. callapply .. this束縛マン

いろいろ、後で追記するかもしれませんが僕なりにまとめてみました。
以上、最後まで読んでいただきありがとうございました。

4
7
2

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
4
7