Kata kunci this
mengacu pada nilai objek yang terikat dengan
fungsi pada saat panggilannya, yang berarti bahwa nilainya akan berbeda bergantung pada
apakah fungsi dipanggil sebagai metode, sebagai fungsi mandiri, atau sebagai
konstruktor.
Saat fungsi dipanggil, fungsi tersebut akan membuat instance kata kunci this
di balik layar sebagai referensi ke objek yang berisi fungsi tersebut, sehingga memberikan akses ke properti dan metode yang ditentukan bersamanya dari dalam cakupannya.
Menggunakan this
dalam beberapa cara mirip dengan menggunakan variabel yang dideklarasikan
dengan const
. Seperti konstanta, this
tidak dapat dihapus dan nilainya tidak dapat ditetapkan ulang, tetapi metode dan properti objek yang dimuat oleh kata kunci this
dapat diubah.
Binding global
Di luar fungsi atau konteks objek, this
merujuk pada properti globalThis
, yang merupakan referensi ke objek global di sebagian besar lingkungan JavaScript. Dalam konteks skrip yang berjalan di browser web,
objek global adalah objek window
:
this;
> Window {0: Window, window: Window, self: Window, document: document, name: '', location: Location, ...}
Di Node.js, globalThis
adalah objek global
:
$ node
Welcome to Node.js v20.10.0.
Type ".help" for more information.
> this
<ref *1> Object [global] {
...
}
Di luar mode ketat, this
juga merujuk ke objek global di dalam fungsi
mandiri, karena Window
induk adalah objek yang secara efektif "memiliki"
fungsi tersebut.
function myFunction() {
console.log( this );
}
myFunction();
> Window {...}
(function() {
console.log( this );
}());
> Window {...}
Saat menggunakan mode ketat, this
memiliki nilai undefined
di dalam fungsi
mandiri:
(function() {
"use strict";
console.log( this );
}());
> undefined
Sebelum mode ketat diperkenalkan, nilai null
atau undefined
untuk this
akan diganti dengan referensi ke objek global. Terkadang Anda mungkin melihat
binding global yang disebut sebagai "binding default" karena perilaku lama ini.
Binding implisit
Ketika sebuah fungsi dipanggil sebagai metode objek, instance this
di dalam metode tersebut mengacu pada objek yang berisi metode, yang memberikan akses ke metode dan properti yang berada di sampingnya:
let myObject = {
myValue: "This is my string.",
myMethod() {
console.log( this.myValue );
}
};
myObject.myMethod();
> "This is my string."
Nilai this
mungkin terlihat seperti ini bergantung pada cara fungsi dan
objek yang mencakupnya ditentukan. Sebagai gantinya, konteks untuk nilai this
adalah
konteks eksekusi saat ini. Dalam hal ini, konteks eksekusinya adalah objek
myObject
memanggil metode myMethod
sehingga myObject
adalah nilai
untuk this
. Hal ini mungkin tampak seperti hal teknis dalam konteks contoh
sebelumnya, tetapi untuk penggunaan this
lanjutan, hal ini merupakan perbedaan penting yang
perlu diingat.
Secara umum, gunakan this
dengan cara yang tidak mengharapkan kode di sekitarnya memiliki
struktur tertentu. Pengecualian untuk aturan ini adalah
Fungsi panah ES5.
this
dalam fungsi panah
Dalam fungsi panah,
this
me-resolve ke binding di
lingkungan yang mencakupnya secara leksikal. Ini berarti bahwa
this
dalam fungsi panah mengacu pada nilai this
dalam
konteks yang mencakup fungsi tersebut:
let myObject = {
myMethod() { console.log( this ); },
myArrowFunction: () => console.log( this ),
myEnclosingMethod: function () {
this.myArrowFunction = () => { console.log(this) };
}
};
myObject.myMethod();
> Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() }
myObject.myArrowFunction();
> Window {...}
Dalam contoh sebelumnya, myObject.myMethod()
mencatat myObject
sebagai objek
yang "memiliki" metode tersebut, tetapi myObject.myArrowFunction()
menampilkan globalThis
(atau undefined
), karena instance this
di dalam fungsi panah
merujuk ke cakupan lingkup tertinggi.
Dalam contoh berikut, myEnclosingMethod
membuat fungsi panah pada objek yang memuatnya saat dieksekusi. Instance this
di dalam
fungsi panah sekarang mengacu pada nilai this
di dalam lingkungan
yang mencakup, yang merupakan metode yang berisi fungsi panah tersebut. Karena
nilai this
di dalam myEnclosingMethod
mengacu pada myObject
, setelah Anda
menentukan fungsi panah, this
di dalam fungsi panah juga mengacu pada
myObject
:
let myObject = {
myMethod() { console.log( this ); },
myEnclosingMethod: function () {
this.myArrowFunction = () => { console.log(this) };
}
};
myObject.myEnclosingMethod();
myObject.myArrowFunction();
> Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() }
Binding eksplisit
Binding implisit menangani sebagian besar kasus penggunaan untuk menggunakan this
. Namun, terkadang Anda
memerlukan nilai this
untuk mewakili konteks eksekusi spesifik, bukan konteks yang diasumsikan. Contoh ilustratif, jika sedikit usang,
bekerja dengan this
dalam fungsi callback setTimeout
,
karena callback ini memiliki konteks eksekusi yang unik:
var myObject = {
myString: "This is my string.",
myMethod() {
console.log( this.myString );
}
};
myObject.myMethod();
> "This is my string."
setTimeout( myObject.myMethod, 100 );
> undefined
Meskipun kekurangan spesifik setTimeout
ini telah diatasi oleh
fitur lain, masalah serupa seperti "kehilangan" this
sebelumnya telah diatasi
dengan membuat referensi eksplisit ke nilai this
dalam cakupan
konteks yang dimaksud. Terkadang Anda mungkin melihat instance this
ditetapkan ke suatu variabel menggunakan ID seperti that
, self
, atau _this
dalam codebase lama. Ini adalah konvensi ID umum untuk variabel yang berisi nilai this
yang diteruskan.
Saat Anda memanggil fungsi menggunakan metode call()
, bind()
, atau apply()
,
this
secara eksplisit merujuk objek yang dipanggil:
let myFunction = function() {
console.log( this.myValue );
}
let myObject = {
"myValue" : "This is my string."
};
myFunction.call( myObject );
> "This is my string."
var myObject = {
myString: "This is my string.",
myMethod() {
console.log( this.myString );
}
};
setTimeout( myObject.myMethod.bind( myObject ), 100 );
> "This is my string."
Binding eksplisit mengganti nilai this
yang disediakan oleh binding implisit.
let myObject = {
"myValue" : "This string sits alongside myMethod.",
myMethod() {
console.log( this.myValue );
}
};
let myOtherObject = {
"myValue" : "This is a string in another object entirely.",
};
myObject.myMethod.call( myOtherObject );
> "This is a string in another object entirely."
Jika fungsi dipanggil dengan cara yang akan menetapkan nilai this
ke undefined
atau null
, nilai tersebut akan diganti dengan globalThis
di luar mode ketat:
let myFunction = function() {
console.log( this );
}
myFunction.call( null );
> Window {...}
Demikian pula, jika fungsi dipanggil dengan cara yang akan memberikan nilai primitif kepada this
, nilai tersebut akan diganti dengan objek wrapper nilai primitif di luar mode ketat:
let myFunction = function() {
console.log( this );
}
let myNumber = 10;
myFunction.call( myNumber );
> Number { 10 }
Dalam mode ketat, nilai this
yang diteruskan tidak dikonversi ke objek dengan cara apa pun, meskipun berupa nilai primitif, null
, atau undefined
:
"use strict";
let myFunction = function() {
console.log( this );
}
let myNumber = 10;
myFunction.call( myNumber );
> 10
myFunction.call( null );
> null
Binding new
Jika class digunakan sebagai konstruktor menggunakan kata kunci new
, this
mengacu pada instance yang baru dibuat:
class MyClass {
myString;
constructor() {
this.myString = "My string.";
}
logThis() {
console.log( this );
}
}
const thisClass = new MyClass();
thisClass.logThis();
> Object { myString: "My string." }
Demikian pula, nilai this
di dalam fungsi konstruktor yang dipanggil menggunakan new
mengacu pada objek yang dibuat:
function MyFunction() {
this.myString = "My string.";
this.logThis = function() {
console.log( this );
}
}
const myObject = new MyFunction();
myObject.logThis();
> Object { myString: "My string.", logThis: logThis() }
Binding pengendali peristiwa
Dalam konteks pengendali peristiwa, nilai this
merujuk ke objek yang
memanggilnya. Di dalam fungsi callback pengendali peristiwa, artinya this
mereferensikan elemen yang terkait dengan pengendali:
let button = document.querySelector( "button" );
button.addEventListener( "click", function( event ) { console.log( this ); } );
Saat pengguna berinteraksi dengan button
dalam cuplikan sebelumnya, hasilnya adalah
objek elemen yang berisi <button>
itu sendiri:
> Button {}
Jika fungsi panah digunakan sebagai callback pemroses peristiwa, nilai this
akan disediakan lagi oleh konteks eksekusi yang terdekat. Di tingkat atas, itu berarti this
di dalam fungsi callback pengendali peristiwa adalah globalThis
(atau undefined
, dalam mode ketat):
let button = document.querySelector( "button" );
button.addEventListener( "click", ( event ) => { console.log( this ); } );
> undefined
Seperti objek lainnya, saat Anda menggunakan metode call()
, bind()
, atau apply()
untuk mereferensikan fungsi callback dari pemroses peristiwa, this
akan merujuk objek secara eksplisit:
let button = document.querySelector( "button" );
let myObject = {
"myValue" : true
};
function handleClick() {
console.log( this );
}
button.addEventListener( "click", handleClick.bind( myObject ) );
> Object { myValue: true }
Menguji pemahaman Anda
Untuk skrip yang berjalan di browser web, apa objek global yang dirujuk this
jika digunakan di luar fungsi atau konteks objek?
window
browser
undefined