Help us understand the problem. What is going on with this article?

JavaScriptのthisの覚え方

More than 5 years have passed since last update.

JavaScriptのthisは同じソースコードでも呼び出し元次第で意味が違ったりして複雑だと思われがちだけど、一回覚えてしまえば簡単だ。

JavaScriptにはthisが4種類ある

これだけをしっかり覚えておけば、後は必要な時に 4種類って何があるんだっけ? と考えれば容易に思い出せる。

ちなみに、下記のコードはブラウザ上で実行することを想定している。(なのでwindowを使う)

トップレベルのthis

グローバルオブジェクトを指す。

var hoge = "fuga";
window.foo = "bar";

// fuga+bar と表示される
console.log(this.hoge + "+" + this.foo);

(function(){
    // 同じくfuga+bar と表示される
    console.log(this.hoge + "+" + this.foo);
})();

コンストラクタ内のthis

作られるインスタンス自身を指す。

var Hoge = function Hoge(msg) {
    this.hoge = msg;
    this.method = function () {
        console.log("method+" + this.hoge);
    }
}

var obj1 = new Hoge("Hello");
var obj2 = new Hoge("World");

// Hello と表示
console.log(obj1.hoge);
// method+Hello と表示
obj1.method();

// World と表示
console.log(obj2.hoge);
// method+World と表示
obj2.method();

// しまったnewを付け忘れたのでHogeの中のthisはグローバルオブジェクトだ!
Hoge("newじゃねーよ!");
// ぎゃーっ! true!
console.log(window.hoge == "newじゃねーよ!");
// ぎゃーっ! method+newじゃねーよ!
window.method();

何かに所属している時のthis

所属しているオブジェクトを指す。

var hoge = {foo:"bar"};
hoge.print1 = function() {
    console.log(this.foo);
};

// bar を表示
hoge.print1();

var func = function() {
    console.log(this.foo);
};
// window.foo が参照されるのでundefined
func();

hoge.print2 = func;
// thisがhogeに変わったので bar と表示される
hoge.print2();

// 一応prototypeも試してみましょうね。
var Hoge = function Hoge(msg) {
    this.message = msg;
};
Hoge.prototype.print = function() {
    console.log("prototype+" + this.message);
}
var obj = new Hoge("Hello");
// prototype+Hello と表示
obj.print();

function#apply とか function#call とかで無理矢理変えられた時のthis

thisを外部からの干渉で無理矢理書き換えられた場合。jQuery使っててclickイベントとか取るとthisが書き換えられている。そういうAPIなの。JavaScriptはNTR文化なの。

あと、document.getElementsByTagName("div") とかやると NodeList が取れる。そこで Array.prototype.slice.call(document.getElementsByTagName("div")) とかすると Array に変換できるハックがある。ってりんごが言ってた。

var hoge = {
    foo: "bar",
    print:function(){
        console.log(this.foo);
    }
};
// 何かに所属している時のthisなので bar と表示
hoge.print();

var paramour = {foo:"NTR"};
// thisをすり替えられたので NTR と表示
hoge.print.call(paramour);

var Hoge = function Hoge(msg) {
    this.message = msg;
}
Hoge.prototype.print = function() {
    console.log("Love " + this.message);
}

var obj1 = new Hoge("sarari-man");
// Love sarari-man と表示
obj1.print();
// アイエエエエ!?ニンジャ!?ニンジャナンデ!?
obj1.print.call({message:"ninja"});

// thisを保護する方法もあるよ
var ProtectedHoge = function ProtectedHoge(msg) {
    this.message = msg;
    // this を保存しておく
    var _this = this;
    this.print = (function(fn) {
        // fn に元々のthis.printが入ってる。
        return function() {
            // 元々のthis.printを_thisに保存しておいた元々のthisを指定して実行しなおす。
            fn.apply(_this, arguments);
        };
    })(this.print);
}
ProtectedHoge.prototype.print = function() {
    console.log("Love " + this.message);
}

var obj2 = new ProtectedHoge("NinjaSlayer");
// ドーモ、ニンジャスレイヤーです。ニンジャ殺すべし。
obj2.print.call({message:"ninja"});

ちなみにCoffeeScriptだとthisの保護も超カンタン -> じゃなくて => 使うだけ。コンパイル後のコード

class ProtectedHoge
  constructor:(@message) ->
  print:() =>
    console.log(@message)

new ProtectedHoge("Fujikido").print()

ねっ?簡単でしょう?

呼び出し元からthisを変えられる仕様にしたヤツを腹を切れ(#^ω^)ビキビキ

vvakame
mercari
フリマアプリ「メルカリ」を、グローバルで開発しています。
https://tech.mercari.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした