「var that = this;」とは何ですか JavaScriptで意味ですか?


351

私が見たJavaScriptファイルで:

function Somefunction(){
   var that = this; 
   ... 
}

これを宣言してthatそれに割り当てる目的は何thisですか?



6
「this」と「that」のハックは、矢印機能には必要ありません。矢印機能を使用すると、「this」は期待どおりに機能します。詳細については、こちらをご覧くださいES6
satguru srivastava

1
ここでは、この概念について説明しますscotch.io/@alZami/understanding-this-in-javascript
AL-


最新の更新された説明はここにあります
Sukrit Gupta

回答:


486

私はこの答えをイラストから始めます:

var colours = ['red', 'green', 'blue'];
document.getElementById('element').addEventListener('click', function() {
    // this is a reference to the element clicked on

    var that = this;

    colours.forEach(function() {
        // this is undefined
        // that is a reference to the element clicked on
    });
});

私の答えはもともとjQueryでこれを示していましたが、少しだけ異なります:

$('#element').click(function(){
    // this is a reference to the element clicked on

    var that = this;

    $('.elements').each(function(){
        // this is a reference to the current element in the loop
        // that is still a reference to the element clicked on
    });
});

this新しい関数を呼び出してスコープを変更すると頻繁に変更されるため、それを使用して元の値にアクセスすることはできません。エイリアスを設定thatすると、の元の値に引き続きアクセスできますthis

個人的にはthat、エイリアスとしての使用は嫌いです。特に関数が数行より長い場合は、それが何を参照しているのかはほとんど明らかではありません。私はいつももっとわかりやすいエイリアスを使っています。上記の例では、おそらくを使用しますclickedEl


149
私はいつも一緒に行きvar self = this;ます。単語thatは変数が何かが何かを意味するようthisです。
デビッドマードック

13
@Davidはい私はそれがやや誤解を招くと思っていました。しかし、クロックフォードが言うように、それが慣習である場合、そのルートを下るのが賢明ですか?私はあなたに完全に同意しますが、もっと理にかなっています。
El Ronnoco、2011

4
@El Ronnoco、しかし「彼は白髪とずんぐりしたひげをしていて、彼の態度は彼の芝生から降りようと子供たちに叫ぶ不機嫌そうな老人を思い起こさせます。」- blogging.compendiumblog.com/blog/software-for-humans/0/0/... ;-p
デヴィッド・マードック

7
@ElRonnoco:しかし、それは権威にとって魅力的です。「有名人」がすべきだと言っていることだけをやったら、私たちは災害に向かっています。
オービットのライトネスレース2013年

3
forEach関数は、関数の結合された第二オプション引数ISを取ります。colours.forEach(function(){/* 'this' is bound correctly --> */}, this);したがって、実際にはで必要とされvar that = thisないメモを追加する必要があります。forEach
Matt Clarkson

107

クロックフォードから

慣例により、私たちはその 変数をプライベートにます。これは、オブジェクトをプライベートメソッドで使用できるようにするために使用されます。これが原因のECMAScript言語仕様におけるエラーの回避策であり、これは、内側の機能のために正しく設定します。

JSフィドル

function usesThis(name) {
    this.myName = name;

    function returnMe() {
        return this;        //scope is lost because of the inner function
    }

    return {
        returnMe : returnMe
    }
}

function usesThat(name) {
    var that = this;
    this.myName = name;

    function returnMe() {
        return that;            //scope is baked in with 'that' to the "class"
    }

    return {
        returnMe : returnMe
    }
}

var usesthat = new usesThat('Dave');
var usesthis = new usesThis('John');
alert("UsesThat thinks it's called " + usesthat.returnMe().myName + '\r\n' +
      "UsesThis thinks it's called " + usesthis.returnMe().myName);

このアラート...

それはデイブと呼ばれていると思います

これは未定義と呼ばれていると考えています


2
おかげで、私には十分に要約できます。
クリス

3
私はそれを読んだ、それは詳細がなかったので理解できなかった、グーグルで検索して、このページを見つけた。私が再び同じ文を指摘されているところ。したがって、反対票。
Aditya MP

3
それは公平な点です。JavaScriptに慣れていない人は、私の答えだけではコンセプトを理解するのが難しいと思います。私は非常に簡潔に回答しました(そして、あなたがグーグルで検索したページへのリンクを作成しました。)寂しい日の答えが最も明確だと思いますが、jQueryの例ではなくプレーンなJSでそれを優先しました。
El Ronnoco 2013

16
私は罪を犯しません。反対票を投じるときにコメントする人に会えてうれしいです!
El Ronnoco 2013

4
クロックフォードの答えの問題は、that変数が彼の例ではまったく使用されていないことです。変数を保持する変数を作成するだけthisで、コードの残りの部分に何らかの効果があるように見えます。
r3m0t 2013

86

これは、内部関数(他の関数の内部で定義された関数)を本来のように機能させるためのハックです。JavaScriptでは、ある関数を別の関数内で定義するthisと、自動的にグローバルスコープに設定されます。これはthis、外側の関数と同じ値を期待しているので、混乱する可能性があります。

var car = {};
car.starter = {};

car.start = function(){
    var that = this;

    // you can access car.starter inside this method with 'this'
    this.starter.active = false;

    var activateStarter = function(){
        // 'this' now points to the global scope
        // 'this.starter' is undefined, so we use 'that' instead.
        that.starter.active = true;

        // you could also use car.starter, but using 'that' gives
        // us more consistency and flexibility
    };

    activateStarter();

};

これは、オブジェクトのメソッドとして(car.start例のように)関数を作成し、そのメソッド内に(のようにactivateStarter)関数を作成する場合に特に問題になります。トップレベルのメソッドthisはオブジェクトを指しますが(この場合はcar)、メソッドですが、内部関数でthisはグローバルスコープを指します。これは苦痛です。

両方のスコープで慣例に従って使用する変数を作成することは、JavaScriptに関するこの非常に一般的な問題の解決策です(jquery関数でも役立ちます)。これが、非常に一般的なサウンド名thatが使用される理由です。これは、言語の欠点を克服するための簡単に認識できる規則です。

El Ronnocoのように、Douglas Crockfordでのヒントは、これは良いアイデアだと考えています。


8
これは受け入れられたものよりも有用な答えだと思います。それは、Crockfordが「それ」を発明した理由を明確にしているのに対し、jQueryについての答えはそうではないからです。
コンスタンティンスモリャニン2013

4
これは実際に受け入れられた答えよりも良い例です。Douglas氏は、「ECMAScript言語仕様のエラーで、内部関数に対してこれが正しく設定されない原因」と説明しています。
kakacii 2013

1
ただし、文法を正しくすることもできます。私はそれがタイプミスに似ていることを知っていますが、この質問は初心者に似ているため、JavaScriptの初心者を混乱させる可能性があります。つまり、次のとおりです。varcar = {}; car.starter = {}; car.start = function(){...}
kakacii 2013

1
@kakaciiありがとう。今修正されました。
Waylon Flinn 2013年

9

またはをthat使用して回避策を講じる場合、の使用は実際には必要ありません。call()apply()

var car = {};
car.starter = {};

car.start = function(){
    this.starter.active = false;

    var activateStarter = function(){
        // 'this' now points to our main object
        this.starter.active = true;
    };

    activateStarter.apply(this);
};

3

this別のスコープを参照したり、別のスコープを参照したりできる場合もあります。たとえば、DOMイベント内でコンストラクターメソッドを呼び出したい場合、この場合this、作成されたオブジェクトではなくDOM要素を参照します。

HTML

<button id="button">Alert Name</button>

JS

var Person = function(name) {
  this.name = name;
  var that = this;
  this.sayHi = function() {
    alert(that.name);
  };
};

var ahmad = new Person('Ahmad');
var element = document.getElementById('button');
element.addEventListener('click', ahmad.sayHi); // => Ahmad

デモ

ASSING意志上記の溶液thisthat、我々はできるし、内部アクセスnameプロパティをsayHiからの方法thatこのように、DOMコールの内部問題なく呼び出すことができます。

別の解決策は、空のthatオブジェクトを割り当て、それにプロパティとメソッドを追加して、それを返すことです。しかし、このソリューションprototypeでは、コンストラクターを失いました。

var Person = function(name) {
  var that = {};
  that.name = name;
  that.sayHi = function() {
    alert(that.name);
  };
  return that;
};

2

ここに例があります `

$(document).ready(function() {
        var lastItem = null;
        $(".our-work-group > p > a").click(function(e) {
            e.preventDefault();

            var item = $(this).html(); //Here value of "this" is ".our-work-group > p > a"
            if (item == lastItem) {
                lastItem = null;
                $('.our-work-single-page').show();
            } else {
                lastItem = item;
                $('.our-work-single-page').each(function() {
                    var imgAlt = $(this).find('img').attr('alt'); //Here value of "this" is '.our-work-single-page'. 
                    if (imgAlt != item) {
                        $(this).hide();
                    } else {
                        $(this).show();
                    }
                });
            }

        });
    });`

したがって、この値はターゲットとするDOM要素に応じて2つの異なる値であることがわかりますが、上のコードに「それ」を追加すると、ターゲットとする「これ」の値が変更されます。

`$(document).ready(function() {
        var lastItem = null;
        $(".our-work-group > p > a").click(function(e) {
            e.preventDefault();
            var item = $(this).html(); //Here value of "this" is ".our-work-group > p > a"
            if (item == lastItem) {
                lastItem = null;
                var that = this;
                $('.our-work-single-page').show();
            } else {
                lastItem = item;
                $('.our-work-single-page').each(function() {
                   ***$(that).css("background-color", "#ffe700");*** //Here value of "that" is ".our-work-group > p > a"....
                    var imgAlt = $(this).find('img').attr('alt'); 
                    if (imgAlt != item) {
                        $(this).hide();
                    } else {
                        $(this).show();
                    }
                });
            }

        });
    });`

..... $(that).css( "background-color"、 "#ffe700"); //ここでは、「that」の値は「.our-work-group> p> a」です。varthat = this; したがって、「this」= '.our-work-single-page'にいても、「that」を使用して以前のDOM要素を操作できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.