Dalam file JavaScript yang saya lihat:
function Somefunction(){
var that = this;
...
}
Apa tujuan menyatakan that
dan menugaskannya this
?
Dalam file JavaScript yang saya lihat:
function Somefunction(){
var that = this;
...
}
Apa tujuan menyatakan that
dan menugaskannya this
?
Jawaban:
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 this
sering berubah ketika Anda mengubah ruang lingkup dengan memanggil fungsi baru, Anda tidak dapat mengakses nilai asli dengan menggunakannya. Mengurangkannya untuk that
memungkinkan Anda masih mengakses nilai asli this
.
Secara pribadi, saya tidak suka menggunakan that
sebagai 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
.
var self = this;
. Kata itu that
sepertinya menyiratkan bahwa variabel itu adalah APA PUN this
.
forEach
fungsi 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
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.
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
that
variabel tidak digunakan dalam contohnya sama sekali. Itu membuatnya tampak seolah-olah hanya membuat holding variabel this
melakukan sesuatu ke seluruh kode.
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 this
secara otomatis diatur ke lingkup global. Ini bisa membingungkan karena Anda berharap this
memiliki 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.start
pada contoh) kemudian membuat fungsi di dalam metode tersebut (seperti activateStarter
). Dalam metode tingkat atas this
menunjuk ke objek itu adalah metode (dalam kasus ini, car
) tetapi dalam fungsi batin this
sekarang 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 that
digunakan. Ini adalah konvensi yang mudah dikenali untuk mengatasi kekurangan dalam bahasa.
Seperti petunjuk El Ronnoco pada Douglas Crockford berpikir ini adalah ide yang bagus.
Penggunaan that
tidak 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);
};
Terkadang this
dapat 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 this
akan 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
Solusi di atas akan mengasumsikan this
untuk that
kemudian kita dapat dan mengakses properti nama di dalam sayHi
metode dari that
, jadi ini dapat dipanggil tanpa masalah di dalam panggilan DOM.
Solusi lain adalah dengan menetapkan that
objek kosong dan menambahkan properti dan metode padanya lalu mengembalikannya. Tetapi dengan solusi ini Anda kehilangan prototype
konstruktor.
var Person = function(name) {
var that = {};
that.name = name;
that.sayHi = function() {
alert(that.name);
};
return that;
};
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.