Apa artinya 'itu = ini;' artinya dalam JavaScript?

351

Dalam file JavaScript yang saya lihat:

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

Apa tujuan menyatakan thatdan menugaskannya this?

Chris
sumber
3
mungkin duplikat dari var self = ini?
Bergi
6
Retasan "ini" dan "itu" tidak diperlukan untuk fungsi panah. Dengan fungsi panah "ini" berfungsi seperti yang diharapkan. Lihat di sini untuk detail lebih lanjut ES6 Dalam Kedalaman: Fungsi panah
satguru srivastava
1
di sini konsep ini dijelaskan scotch.io/@alZami/understanding-this-in-javascript
AL-zami
Penjelasan yang bagus tentang misterius perilaku ini berdasarkan konteks di sini
RBT
Penjelasan terbaru & terkini dapat ditemukan di sini
Sukrit Gupta

Jawaban:

486

Saya akan memulai jawaban ini dengan ilustrasi:

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

Jawaban saya awalnya menunjukkan ini dengan jQuery, yang hanya sedikit berbeda:

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

Karena thissering berubah ketika Anda mengubah ruang lingkup dengan memanggil fungsi baru, Anda tidak dapat mengakses nilai asli dengan menggunakannya. Mengurangkannya untuk thatmemungkinkan Anda masih mengakses nilai asli this.

Secara pribadi, saya tidak suka menggunakan thatsebagai alias. Jarang jelas apa yang dimaksud, terutama jika fungsinya lebih panjang dari beberapa baris. Saya selalu menggunakan alias yang lebih deskriptif. Dalam contoh saya di atas, saya mungkin akan menggunakan clickedEl.

lonesomeday
sumber
149
Saya biasanya pergi dengan var self = this;. Kata itu thatsepertinya menyiratkan bahwa variabel itu adalah APA PUN this.
David Murdoch
13
@ David Ya, saya pikir itu agak menyesatkan. Tetapi jika, seperti yang dikatakan Crockford, itu adalah kebaktian, apakah bijaksana untuk menempuh jalan itu. Saya sepenuhnya setuju dengan Anda, jauh lebih masuk akal.
El Ronnoco
4
@ El Ronnoco, tapi "Dia punya rambut abu-abu dan jenggot yang lusuh dan sikapnya mengingatkan orang tua pemarah yang berteriak pada anak-anak untuk turun dari halamannya." - blogging.compendiumblog.com/blog/software-for-humans/0/0/… ;-p
David Murdoch
7
@ ElRonnoco: Namun, itu menarik bagi otoritas. Jika kita hanya melakukan apa yang seharusnya dilakukan oleh "orang-orang terkenal", kita akan menuju kehancuran.
Lightness Races dalam Orbit
3
The forEachfungsi mengambil argumen kedua yaitu opsional yang pengikatan fungsi. colours.forEach(function(){/* 'this' is bound correctly --> */}, this);Jadi catatan harus ditambahkan yang sebenarnyavar that = this tidak diperlukan . forEach
Matt Clarkson
107

Dari Crockford

Dengan konvensi, kita membuat pribadi yang variabel. Ini digunakan untuk membuat objek tersedia untuk metode pribadi. Ini adalah solusi untuk kesalahan dalam Spesifikasi Bahasa Naskah ECMAS yang menyebabkan hal ini diatur secara tidak benar untuk fungsi-fungsi bagian dalam.

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

Lansiran ini ...

Penggunaan Menurutnya itu disebut Dave

Penggunaan Ini berpikir itu disebut tidak terdefinisi

El Ronnoco
sumber
2
Terima kasih, jumlah itu cukup baik untuk saya.
Chris
3
Saya membaca itu, tidak mengerti karena tidak ada detail, mencari di Google, menemukan halaman ini. Di mana saya lagi menunjuk ke kalimat yang sama. Karena itu downvote.
Aditya MP
3
Itu poin yang adil, saya akan mengatakan bahwa seseorang yang tidak terbiasa dengan JavaScript akan mengalami kesulitan memahami konsep dari jawaban saya sendiri. Saya menjawab dengan sangat singkat (dan saya melakukan tautan ke halaman yang Anda cari di Google). Saya akan mengatakan jawaban lonesomeday adalah yang paling jelas, meskipun saya masih lebih suka menggunakan JS polos dibandingkan dengan contoh jQuery.
El Ronnoco
16
Saya tidak tersinggung. Sangat menyenangkan melihat seseorang yang berkomentar saat downvoting!
El Ronnoco
4
Masalah dengan jawaban Crockford adalah thatvariabel tidak digunakan dalam contohnya sama sekali. Itu membuatnya tampak seolah-olah hanya membuat holding variabel thismelakukan sesuatu ke seluruh kode.
r3m0t
86

Ini adalah retasan untuk membuat fungsi-fungsi dalam (fungsi-fungsi yang didefinisikan di dalam fungsi-fungsi lain) bekerja lebih seperti seharusnya. Dalam javascript ketika Anda mendefinisikan satu fungsi di dalam yang lain thissecara otomatis diatur ke lingkup global. Ini bisa membingungkan karena Anda berharap thismemiliki nilai yang sama dengan fungsi luar.

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

};

Ini secara khusus merupakan masalah ketika Anda membuat fungsi sebagai metode suatu objek (seperti car.startpada contoh) kemudian membuat fungsi di dalam metode tersebut (seperti activateStarter). Dalam metode tingkat atas thismenunjuk ke objek itu adalah metode (dalam kasus ini, car) tetapi dalam fungsi batin thissekarang menunjuk ke lingkup global. Ini menyakitkan.

Membuat variabel untuk digunakan oleh konvensi di kedua cakupan adalah solusi untuk masalah yang sangat umum ini dengan javascript (meskipun itu berguna dalam fungsi jquery juga). Inilah sebabnya mengapa nama terdengar yang sangat umum thatdigunakan. Ini adalah konvensi yang mudah dikenali untuk mengatasi kekurangan dalam bahasa.

Seperti petunjuk El Ronnoco pada Douglas Crockford berpikir ini adalah ide yang bagus.

Waylon Flinn
sumber
8
Saya kira ini adalah jawaban yang lebih berguna daripada yang diterima. Karena itu menjelaskan alasan mengapa Crockford menemukan "itu" sementara jawaban tentang jQuery tidak.
Konstantin Smolyanin
4
Ini sebenarnya adalah contoh yang lebih baik daripada jawaban yang diterima. Ini menjelaskan bagaimana rasanya sebagai "kesalahan dalam Spesifikasi Bahasa ECMAScript yang menyebabkan hal ini diatur secara tidak benar untuk fungsi bagian dalam" kata Douglas.
kakacii
1
Anda mungkin ingin membuatnya menjadi tata bahasa yang benar. Saya tahu ini lebih seperti kesalahan ketik, tetapi bisa membingungkan pemula javascript karena pertanyaan ini lebih seperti pemula. Maksud saya seharusnya: var car = {}; car.starter = {}; car.start = function () {...}
kakacii
1
@kakacii Terima kasih. Diperbaiki sekarang
Waylon Flinn
9

Penggunaan thattidak benar-benar diperlukan jika Anda membuat solusi dengan penggunaan call()atau 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);
};
Adela
sumber
3

Terkadang thisdapat merujuk ke ruang lingkup lain dan merujuk ke sesuatu yang lain, misalnya misalkan Anda ingin memanggil metode konstruktor di dalam peristiwa DOM, dalam hal ini thisakan merujuk ke elemen DOM bukan objek yang dibuat.

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

Demo

Solusi di atas akan mengasumsikan thisuntuk thatkemudian kita dapat dan mengakses properti nama di dalam sayHimetode dari that, jadi ini dapat dipanggil tanpa masalah di dalam panggilan DOM.

Solusi lain adalah dengan menetapkan thatobjek kosong dan menambahkan properti dan metode padanya lalu mengembalikannya. Tetapi dengan solusi ini Anda kehilangan prototypekonstruktor.

var Person = function(name) {
  var that = {};
  that.name = name;
  that.sayHi = function() {
    alert(that.name);
  };
  return that;
};
Ahmad Ajmi
sumber
2

Berikut ini contohnya `

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

        });
    });`

Sehingga Anda dapat melihat bahwa nilai ini adalah dua nilai yang berbeda tergantung pada elemen DOM yang Anda targetkan tetapi ketika Anda menambahkan "itu" ke kode di atas Anda mengubah nilai "ini" yang Anda targetkan.

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

        });
    });`

..... $ (itu) .css ("warna latar belakang", "# ffe700"); // Di sini nilai "itu" adalah ".our-work-group> p> a" karena nilai var yang = ini; jadi meskipun kita berada di "this" = '.our-work-single-page', kita masih dapat menggunakan "itu" untuk memanipulasi elemen DOM sebelumnya.

stacksonstacksonstacks
sumber