'Var that = this;' ne yapar? JavaScript demek?


351

Bir JavaScript dosyasında gördüm:

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

Bunu beyan thatve atamanın amacı nedir this?



6
Ok fonksiyonları için "this" ve "that" hack'lerine gerek yoktur. Ok fonksiyonlarıyla "bu" beklendiği gibi çalışır. Daha fazla bilgi için buraya bakın ES6 Derinlik: Ok fonksiyonları
satguru srivastava

1
Burada bunun kavramı açıklanmıştır scotch.io/@alZami/understanding-this-in-javascript
AL-zami

Bağlamına göre gizemli bu davranışı üzerinde büyük bir açıklama burada
MHK

En son ve güncellenmiş açıklama burada
Sukrit Gupta

Yanıtlar:


486

Bu cevaba bir örnekle başlayacağım:

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
    });
});

Cevabım bunu aslında çok az farklı olan jQuery ile gösterdi:

$('#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
    });
});

Çünkü thisyeni bir işlevini çağırarak kapsamını değiştirmek zaman sık sık değişir, bunu kullanarak özgün değeri erişemez. İçin diğer adının thatasıl değerine erişmenizi sağlar this.

Şahsen, thattakma ad olarak kullanılmasından hoşlanmıyorum . Özellikle işlevler birkaç satırdan daha uzunsa, neye atıfta bulunduğu nadiren açıktır. Her zaman daha açıklayıcı bir takma ad kullanırım. Yukarıdaki örneklerimde muhtemelen kullanırım clickedEl.


149
Ben genellikle giderim var self = this;. Kelime thatdeğişkeni bir şey var gibi görünüyor AMA this.
David Murdoch

13
@David Evet Bunun biraz yanıltıcı olduğunu düşündüm . Ama eğer Crockford'un dediği gibi, bu bir kongre ise, o rotadan aşağı inmek akıllıca olur. Sana tamamen katılıyorum, çok daha mantıklı.
El Ronnoco

4
@El Ronnoco, ama "Gri saçları ve tırmalamak sakalı var ve tavrı, çocuklarına çimlerinden çıkmasını isteyen huysuz yaşlı bir adamı akla getiriyor." - blogging.compendiumblog.com/blog/software-for-humans/0/0/… ;-p
David Murdoch

7
@ElRonnoco: Bu yine de otoriteye hitap ediyor. Eğer sadece "ünlü insanlar" dediğimiz şeyi yaparsak, felakete yöneliriz.
Yörüngedeki Hafiflik Yarışları

3
forEachİşlev, bağlanması olan bir ikinci isteğe bağlı bir argümandır alır. colours.forEach(function(){/* 'this' is bound correctly --> */}, this);Dolayısıyla var that = this, aslında gerekli olmayan bir not eklenmelidir forEach.
Matt Clarkson

107

Gönderen Crockford

Geleneksel olarak, bu değişkeni özel yapıyoruz . Bu, nesneyi özel yöntemlerin kullanımına sunmak için kullanılır. Bu neden ECMAScript Dil Şartnamede bir hata için geçici bir çözümdür bu iç fonksiyonlar için yanlış ayarlanmış olması.

JS Fiddle

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);

Bu uyarılar ...

Dave dendiğini düşünen

Bu, tanımsız olarak adlandırıldığını düşünüyor


2
Teşekkürler, benim için yeterince iyi özetliyor.
Chris

3
Bunu okudum, anlamadım çünkü ayrıntısı yoktu, Google'da aradı, bu sayfayı buldu. Yine aynı cümleyi işaret ettiğim yer. Bu yüzden aşağı oy.
Aditya MP

3
Bu adil bir nokta, JavaScript'e aşina olmayan birinin kavramı tek başına cevabımdan kavramada zorluk çekeceğini söyleyebilirim. Çok kısaca cevap verdim (ve sizin için Googled olduğunuz sayfaya bağlantı verdim ..) Yalnız günün cevabının en açık olduğunu söyleyebilirim, ancak yine de bir jQuery örneğinin aksine düz JS'de tercih ederdim.
El Ronnoco

16
Suçlanmam. Aşağı oy verirken yorum yapan birini görmek güzel!
El Ronnoco

4
Crockford'un cevabındaki sorun, thatdeğişkenin örneğinde hiç kullanılmamasıdır. Bir değişken tutma oluşturmak thiskodun geri kalanına bir şey yapıyormuş gibi görünmesini sağlar .
r3m0t

86

Bu, iç işlevlerin (diğer işlevlerde tanımlanan işlevler) olması gerektiği gibi çalışmasını sağlamak için bir hack'tir. Javascript içinde bir işlevi tanımladığınızda başka bir işlev thisotomatik olarak genel kapsama ayarlanır. thisDış işlevde olduğu gibi aynı değere sahip olmayı beklediğiniz için bu kafa karıştırıcı olabilir .

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();

};

Bu, özellikle bir nesnenin yöntemi olarak bir işlev oluşturduğunuzda ( car.startörnekte olduğu gibi activateStarter) ve bu yöntemin içinde (örneğin) bir işlev oluşturduğunuzda bir sorundur . Üst düzey yöntemde thisnesneye işaret eder (bu durumda car) bir yöntemdir, ancak iç işlevde thisartık küresel kapsamı göstermektedir. Bu bir acı.

Her iki kapsamda da kural olarak kullanılacak bir değişken oluşturmak, javascript ile ilgili bu çok genel soruna bir çözümdür (jquery işlevlerinde de yararlıdır). Bu yüzden genel ses adı thatkullanılır. Dilde bir eksikliğin üstesinden gelmek için kolayca tanınabilir bir konvansiyon.

El Ronnoco gibi Douglas Crockford'un ipuçları bunun iyi bir fikir olduğunu düşünüyor.


8
Sanırım bu, cevaplanandan daha yararlı bir cevap. Çünkü jQuery hakkında cevap vermese de, Crockford'un neden "bu" icat ettiğinin nedenini açıklıyor.
Konstantin Smolyanin

4
Bu aslında kabul edilen cevaptan daha iyi bir örnek. Douglas'ın "ECMAScript Dil Spesifikasyonunda bunun iç fonksiyonlar için yanlış ayarlanmasına neden olan bir hata" olarak nasıl bir şey olduğunu açıklıyor.
kakacii

1
Yine de dilbilgisini doğru yapmak isteyebilirsiniz. Ben daha çok bir yazım hatası gibi biliyorum, ama bu soru daha yeni başlayanlar gibi javascript yeni başlayanlar karıştırabilir. Yani öyle olmalı: var car = {}; car.starter = {}; car.start = function () {...}
kakacii

1
@kakacii Teşekkürler. Şimdi düzeltildi.
Waylon Flinn

9

Kullanılması thatEğer kullanımı ile geçici bir çözüm yaparsanız gerçekten gerekli değildir call()ya 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

Bazen thisbaşka bir kapsama başvurabilir ve başka bir şeye başvurabilir, örneğin bir DOM olayı içindeki bir yapıcı yöntemini çağırmak istediğinizi varsayalım, bu durumda thisoluşturulan nesneye değil DOM öğesine atıfta bulunun.

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

gösteri

Yukarıdaki çözüm this,that daha sonra biz ve iç erişim ismi özelliğini sayHidan yöntemle thatbu yüzden, DOM çağrısı içinde sorunsuz çağrılabilir.

Başka bir çözüm, boş bir thatnesne atamak ve ona özellikler ve yöntemler eklemek ve sonra geri döndürmektir. Ancak bu çözümle kurucuyu kaybettiniz prototype.

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

2

İşte bir örnek `

$(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();
                    }
                });
            }

        });
    });`

Böylece, bu değerin, hedeflediğiniz DOM öğesine bağlı olarak iki farklı değer olduğunu görebilirsiniz, ancak yukarıdaki koda "o" eklediğinizde, hedeflediğiniz "bu" değerinin değerini değiştirirsiniz.

`$(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 ("arka plan rengi", "# ffe700"); // Burada "that" değeri ".our-work-group> p> a" olur, çünkü var değeri = this; "this" = '.our-work-single-page "konumunda olmamıza rağmen, yine de önceki DOM öğesini değiştirmek için" that "komutunu kullanabiliriz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.