Fungsi panah dan kata kunci `this` dalam JavaScript

Pembaharuan Terakhir: 02/10/2026
  • Fungsi panah menyediakan sintaks dan penangkapan yang ringkas. this secara leksikal dari lingkup sekitarnya, alih-alih menciptakan ikatan sendiri.
  • Nilai dari this Dalam fungsi reguler, hal ini bergantung pada bagaimana fungsi tersebut dipanggil, yang memengaruhi fungsi, metode, konstruktor, kelas, dan callback.
  • Fungsi panah ideal untuk callback dan metode array, tetapi bukan pilihan yang baik untuk metode objek, penanganan event DOM, dan konstruktor.
  • Memahami kapan this Perbedaan antara fungsi dinamis dan leksikal sangat penting untuk menghindari bug yang sulit dideteksi dan untuk memilih antara fungsi panah dan fungsi tradisional.

Fungsi panah dan `this` dalam JavaScript

Jika Anda pernah masuk this Jika Anda menemukan hasil yang sangat berbeda dalam berbagai fungsi JavaScript, Anda tidak sendirian. Banyak pengembang menemui kasus di mana sebuah metode mencetak objek yang diharapkan, sedangkan fungsi panah mencetak... window, dan panah bersarang tiba-tiba "secara ajaib" menunjuk kembali ke objek di sekitarnya. Memahami mengapa hal itu terjadi adalah kunci untuk menulis kode yang dapat diprediksi dan bebas bug.

Fungsi panah dan this Kata kunci membentuk salah satu kombinasi terpenting (dan paling disalahpahami) dalam JavaScript modern. Fungsi panah tampak seperti sintaks yang lebih pendek, tetapi di balik layar, fungsi ini mengubah cara kerja suatu sistem. this Bagaimana callback ditangani, bagaimana cara kerjanya, dan bahkan kapan Anda harus atau tidak boleh menggunakannya sebagai metode. Mari kita bahas semuanya langkah demi langkah, dari sintaks hingga konteks eksekusi, menggunakan bahasa Inggris sederhana dan banyak contoh praktis.

Sintaks fungsi panah tanpa kebingungan

Fungsi panah adalah ekspresi fungsi yang ditulis dengan => sintaks alih-alih function kata kunci. Secara konseptual, Anda dapat menganggapnya sebagai cara ringkas untuk menulis: "ambil parameter ini, evaluasi ekspresi atau blok kode ini, dan kembalikan sebuah nilai." Pada dasarnya, itu tetap fungsi, tetapi perilakunya berbeda dalam beberapa hal penting.

Fungsi panah paling dasar dipetakan langsung ke ekspresi fungsi reguler. Sebagai contoh, ekspresi fungsi klasik ini:

const multiplyByTwo = function (value) { return value * 2; };

Dapat ditulis ulang sebagai fungsi panah seperti ini:

const multiplyByTwo = (value) => { return value * 2; };

Fungsi panah akan terlihat jelas ketika tubuh memiliki ekspresi tunggal. Jika isi pernyataan hanya berupa satu kalimat yang mengembalikan sesuatu, Anda dapat menghilangkan tanda kurung kurawal dan keterangan eksplisit. return, memungkinkan pengembalian implisit:

const multiplyByTwo = value => value * 2;

Jika hanya ada satu parameter, Anda dapat menghilangkan tanda kurung di sekitarnya, tetapi hanya dalam kasus spesifik tersebut. So x => x * 2 Ini valid, tetapi jika Anda memiliki nol atau lebih parameter, Anda harus tetap menggunakan tanda kurung:

  • Parameter nol: () => 42
  • Satu parameter: x => x * 2 or (x) => x * 2
  • Dua parameter atau lebih: (x, y) => x + y

Jika Anda memerlukan lebih dari satu pernyataan dalam isi, Anda harus menggunakan tanda kurung kurawal dan tanda kurung siku yang jelas. return. Dalam situasi tersebut, fungsi panah berperilaku seperti fungsi biasa terkait nilai kembalian: tidak ada return, tidak ada nilai yang dikembalikan.

const feedCat = (status) => {
if (status === 'hungry') {
return 'Feed the cat';
} else {
return 'Do not feed the cat';
}
};

Berhati-hatilah saat mengembalikan literal objek dari fungsi panah, karena tanda kurung kurawal objek dapat disalahartikan sebagai isi fungsi. Untuk menghindari ambiguitas tersebut, bungkus literal objek dalam tanda kurung agar JavaScript tahu bahwa itu adalah ekspresi yang akan dikembalikan:

const toObject = value => ({ result: value });

Satu hal lagi: fungsi panah selalu berupa ekspresi, bukan deklarasi. Artinya, nilai-nilai tersebut harus ditetapkan ke variabel, properti, atau diteruskan sebagai argumen; nilai-nilai tersebut tidak dapat berdiri sendiri seperti function myFunc() {}, dan mereka tidak diangkat dengan cara yang sama seperti deklarasi fungsi, jadi Anda tidak dapat memanggilnya sebelum didefinisikan.

Apa sebenarnya itu this dalam JavaScript?

Kata kuncinya this adalah pengikatan dinamis yang dibuat JavaScript untuk Anda saat mengeksekusi fungsi atau metode kelas. Anda dapat menganggapnya sebagai parameter tak terlihat yang nilainya bergantung pada bagaimana dan di mana fungsi tersebut dipanggil. Hal ini membuatnya ampuh dan fleksibel, tetapi juga menjadi sumber kebingungan yang besar.

Dalam fungsi non-ketat, this selalu menghasilkan suatu objek; dalam mode ketat, nilainya bisa berupa apa saja, termasuk undefined. JavaScript menentukan nilai tersebut berdasarkan konteks eksekusi: fungsi biasa, panggilan metode, panggilan konstruktor, kelas, cakupan global, atau fungsi panah.

Pada level teratas dari sebuah skrip klasik (bukan modul), this mengacu pada globalThis, yang biasanya merupakan milik browser. window obyek. Jadi, perbandingan berikut di browser akan benar:

console.log(this === window); // true

Pada fungsi yang bukan fungsi panah, this ditentukan sepenuhnya oleh lokasi panggilan. Jika Anda menelepon obj.method()lalu di dalam method nilai this is objJika Anda mengambil fungsi yang sama dan memanggilnya secara terpisah sebagai fn() dalam mode ketat, this menjadi undefined; dalam mode non-ketat, JavaScript “mengganti” this dengan globalThis.

Yang terpenting, yang mattered bukanlah di mana fungsi tersebut didefinisikan, tetapi bagaimana fungsi tersebut dipanggil. Suatu metode dapat berada di rantai prototipe atau ditugaskan kembali ke objek yang berbeda dan tetap dapat dilihat this seperti objek apa pun yang sebenarnya digunakan pada saat pemanggilan. Melewatkan sebuah metode seringkali mengubah nilainya. this kecuali jika Anda secara eksplisit memperbaikinya.

Ada juga alat untuk mengontrolnya. this secara eksplisit: call, apply, bind, dan Reflect.apply. Ini memungkinkan Anda untuk "menyuntikkan" yang diinginkan this nilai: fn.call(obj, arg1, arg2) akan mengeksekusi fn dengan this mulai objAturan substitusi yang sama berlaku dalam mode non-ketat: jika Anda lulus null or undefined as this, mereka digantikan dengan globalThis; objek primitif dimasukkan ke dalam objek pembungkusnya.

Fungsi callback menambahkan lapisan perantara lain, karena this dikendalikan oleh siapa pun yang memanggil fungsi callback Anda. Metode iterasi array, Promise konstruktor, dan API serupa biasanya memanggil callback dengan this mulai undefined (atau objek global dalam mode longgar). Beberapa API, seperti Array.prototype.forEach or Set.prototype.forEach, menerima terpisah thisArg parameter yang dapat Anda gunakan untuk mengatur callback. this.

API lainnya sengaja memanggil callback dengan kustom. this nilai-nilai. Sebagai contoh, reviver argumen untuk JSON.parse dan replacer untuk JSON.stringify menerima this Terikat pada objek yang memiliki properti yang sedang diproses. Penanganan peristiwa di DOM terikat pada elemen tempatnya terpasang ketika ditulis dengan cara "klasik".

Ide intinya: fungsi panah tidak menciptakan fungsi panahnya sendiri. this

Ciri khas dari fungsi panah adalah bahwa fungsi tersebut tidak pernah membuat objek baru. this mengikat. Sebaliknya, mereka menutup (atau "menangkap") this dari lingkungan leksikal di sekitarnya pada saat dibuat. Ketika panah dieksekusi nanti, ia hanya menggunakan kembali nilai yang ditangkap tersebut, terlepas dari bagaimana Anda memanggilnya.

Dalam praktiknya, fungsi panah berperilaku seolah-olah terikat secara otomatis secara permanen ke this dari cakupan luarnya. Inilah mengapa metode seperti call, apply, dan bind tidak bisa berubah this untuk fungsi panah: thisArg Argumen tersebut diabaikan begitu saja. Anda masih dapat meneruskan parameter biasa melaluinya, tetapi... this Nilai terkunci.

Perhatikan cuplikan kode ini dalam lingkup global sebuah file skrip:

const arrow = () => console.log(this);
arrow();

Karena panah didefinisikan dalam kode global, maka this adalah global this (khas window (dalam skrip browser), dan itu tidak pernah berubah. panggilan arrow Sebagai fungsi biasa, menugaskannya ke properti, atau meneruskannya akan selalu mencatat objek global yang sama ketika dipanggil dalam konteks ini.

Perilaku yang benar-benar menarik muncul ketika Anda menyusun fungsi panah di dalam fungsi atau metode biasa. Karena panah tersebut menangkap fungsi luar this, ini menjadi alat yang ampuh untuk callback yang perlu merujuk kembali ke objek induknya tanpa cara yang biasa. .bind(this) upacara.

const counter = {
id: 42,
start() {
setTimeout(() => {
console.log(this.id); // uses counter.id
}, 1000);
},
};

If start menggunakan fungsi anonim tradisional di dalam setTimeoutAnda perlu mengikat secara manual. this atau menyimpannya ke dalam variabel. Dengan panah, fungsi callback secara otomatis mewarisi this dari start, Yang counter, sehingga this.id cetakan 42 seperti yang dimaksudkan.

Keterkaitan leksikal ini juga menjelaskan pertanyaan klasik “mengapa this Pertanyaan "ubah" muncul saat menggunakan tanda panah dalam literal objek. Perhatikan kedua benda ini:

const obj1 = {
speak() {
console.log(this);
}
};

const obj2 = {
speak: () => {
console.log(this);
}
};

panggilan obj1.speak() cetakan obj1, Karena speak adalah metode biasa dan this diatur berdasarkan lokasi panggilan. Sebaliknya, obj2.speak() mencatat bagian luar this (sering window (di browser), karena panah tersebut tidak menggunakan objek sebagai panahnya. thisObjek literal itu sendiri tidak menciptakan objek baru. this cakupan; hanya isi fungsi yang melakukan itu, dan fungsi panah melewatkan langkah itu.

Sekarang perhatikan sebuah metode objek yang membuat dan langsung memanggil panah dalam:

const obj3 = {
speak() {
(() => {
console.log(this);
})();
}
};

obj3.speak();

Dalam situasi ini, fungsi panah dalam mewarisi this dari speak, Yang obj3 ketika dipanggil sebagai obj3.speak(). Meskipun panah tersebut merupakan fungsi bersarang yang dipanggil secara langsung, panah tersebut tetap menunjuk ke obj3, bukan objek global. Itulah esensi dari leksikal. this: hal ini mengikuti cakupan sekitarnya, bukan lokasi panggilan panah itu sendiri.

this di seluruh fungsi, objek, dan konstruktor

Untuk benar-benar menguasai fungsi panah dan this, akan sangat membantu jika kita melihat bagaimana this Berfungsi di setiap konteks utama: fungsi reguler, metode, konstruktor, kelas, dan cakupan global. Setelah aturan-aturan tersebut jelas, perilaku panah akan jauh lebih mudah dipahami.

Dalam fungsi biasa (non-panah), this Tergantung 100% pada bagaimana fungsi tersebut dipanggil. Jika Anda menelepon fn() dalam mode ketat, this is undefined; dalam mode ceroboh, substitusi menghasilkan this menjadi globalThisJika Anda menelepon obj.fn(), kemudian this is obj. Bergerak fn ke objek yang berbeda atau ke variabel dan nilai dari this akan bertindak sesuai dengan itu.

Dalam sebuah metode yang didefinisikan pada literal objek, this adalah objek yang diakses oleh metode tersebut, bukan berarti objek tempat metode tersebut awalnya didefinisikan. If obj.__proto__ memiliki sebuah metode dan Anda memanggilnya obj.method()lalu di dalam method, this is obj, bukan prototipe.

Konstruktor adalah kasus khusus lainnya: ketika Anda memanggil fungsi dengan new, this terikat pada instance objek yang baru saja dibuat. Misalnya, di function User(name) { this.name = name; }, memanggil new User('Alex') set this ke yang baru User objek. Jika konstruktor secara eksplisit mengembalikan objek non-primitif, objek yang dikembalikan tersebut menggantikan this sebagai nilai akhir dari new ekspresi.

Sintaks kelas dibangun berdasarkan aturan-aturan ini dengan dua konteks utama: instance dan statis. Di dalam konstruktor atau metode instance, this menunjuk ke instance kelas yang sedang Anda kerjakan. Di dalam metode statis atau blok inisialisasi statis, this mengacu pada kelas itu sendiri (atau kelas turunan ketika dipanggil melalui pewarisan). Bidang instance dievaluasi dengan this terikat pada instance baru; lihat bidang statis this sebagai konstruktor kelas.

Konstruktor kelas turunan berperilaku sedikit berbeda: sampai Anda memanggilnya super(), tidak ada yang bisa digunakan this. Memohon super() menginisialisasi this dengan mendelegasikan ke konstruktor dasar; pengembalian sebelum melakukan itu di konstruktor turunan hanya diperbolehkan jika Anda secara eksplisit mengembalikan objek yang berbeda.

Dalam konteks global, this Tergantung pada bagaimana lingkungan JavaScript membungkus dan mengeksekusi kode Anda. Dalam skrip browser klasik, tingkat atas this adalah objek global; dalam modul ES, tingkat atas this selalu undefinedModul Node.js CommonJS dibungkus secara internal dan biasanya dieksekusi dengan this mulai module.exportsAtribut penanganan peristiwa sebaris di HTML dieksekusi dengan this diatur ke elemen tempat mereka terpasang.

Satu detail yang halus namun penting: literal objek itu sendiri tidak memperkenalkan hal baru. this cakupan. Writing const obj = { value: this }; di dalam skrip akan membuat obj.value sama dengan bagian luar this, bukan objeknya. Hanya isi fungsi (dan isi kelas) yang membuat khusus. this pengikatan; panah sengaja melewati langkah ini dan mewarisi.

Mengapa fungsi panah sangat bagus untuk callback (dan kapan tidak)

Karena fungsi panah tertutup this, mereka sangat cocok untuk banyak skenario callback di mana Anda ingin callback tersebut tetap merujuk pada objek atau konteks di sekitarnya. Ini sangat berguna terutama untuk timer, promise, dan metode array seperti map, filter, dan reduce.

Bayangkan sebuah metode yang perlu memperbarui beberapa properti berulang kali menggunakan setInterval. Dengan menggunakan fungsi tradisional, this di dalam fungsi callback akan secara default menggunakan objek global (atau menjadi undefined (dalam mode ketat), jadi this.count tidak akan mengarah ke instance Anda. Dengan fungsi panah, callback secara alami menggunakan this dari metode luar.

function Counter() {
this.count = 0;

setInterval(() => {
this.count++;
}, 1000);
}

Berkat panah itu, this Di dalam interval callback mengacu pada Counter misalnya, bukan window. Jika callback tersebut merupakan fungsi biasa, Anda perlu melakukan salah satu dari berikut ini: .bind(this) atau variabel perantara seperti const self = this; untuk menyimpan referensi tersebut.

Fungsi panah juga menyederhanakan kode yang menggunakan metode array, di mana Anda seringkali tidak peduli dengan hal tersebut. this sama sekali. Saat Anda meneruskan fungsi tradisional sebagai callback, implisit this biasanya undefinedDan Anda mungkin lupa akan hal itu. Panah membuat secara visual jelas bahwa fungsi tersebut hanyalah pemetaan murni dari input ke output.

const numbers = [1, 2, 3];
const doubled = numbers.map(n => n * 2);

Namun, ada kasus-kasus penting di mana fungsi panah bukanlah pilihan yang tepat, terutama ketika Anda memang membutuhkan tipe data dinamis. this. Dua anti-pola klasik adalah menggunakan fungsi panah sebagai metode objek dan sebagai penangan peristiwa DOM yang bergantung pada this menjadi elemen tersebut.

Pertimbangkan sebuah objek yang melacak kehidupan seekor kucing:

const cat = {
lives: 9,
jump: () => {
this.lives--; // bug: this is not cat
},
};

cat.jump();

Sejak jump adalah anak panah, this tidak merujuk pada cat tetapi untuk apa pun this Di situlah literal objek dibuat (seringkali objek global). Yang dimaksud this.lives-- Entah melempar pengecualian (dalam mode ketat) atau diam-diam memodifikasi sesuatu yang tidak terkait. Menggunakan sintaks metode reguler di sini adalah langkah yang tepat.

Pendengar peristiwa DOM serupa: pola standar this.classList.toggle('on') di dalam callback event bergantung pada this menjadi elemen yang memicu peristiwa tersebut. Dengan fungsi panah, this tidak lagi menunjuk ke elemen tersebut, sehingga kode menjadi rusak.

const button = document.getElementById('press');

button.addEventListener('click', () => {
this.classList.toggle('on'); // this is not button
});

Dalam situasi ini, penangan (handler) harus berupa fungsi normal sehingga this terikat oleh browser ke elemen tombol. Fungsi panah (arrow function) sama sekali tidak bisa langsung digunakan sebagai pengganti jika logika Anda mengharapkan hal tersebut. this menjadi target peristiwa dinamis.

Kelemahan halus lainnya adalah bahwa fungsi panah secara sintaksis bersifat anonim. Biasanya, stack trace tidak memiliki nama sendiri (selain variabel yang ditugaskan kepadanya), yang dapat membuat stack trace sedikit kurang deskriptif dan rekursi sedikit lebih rumit. Dalam sebagian besar kode dunia nyata, ini adalah kompromi yang dapat dikelola, tetapi perlu diingat.

Kasus khusus: getter, setter, metode terikat, dan kondisi yang tidak lazim.

Pemain yang mengambil bola (getter) dan pemain yang mengatur bola (setter) mengikuti aturan "lokasi panggilan" yang sama: this adalah objek tempat properti tersebut diakses, bukan objek tempat properti tersebut awalnya didefinisikan. Jika sebuah getter diwarisi dari sebuah prototipe dan Anda memanggilnya pada objek turunan, this Di dalam getter, yang dimaksud adalah objek turunan.

Metode terikat yang dibuat dengan Function.prototype.bind Memberikan perilaku yang agak mirip dengan fungsi panah, tetapi pada level fungsi biasa. Saat Anda menelepon f.bind(obj)Anda membuat fungsi baru yang this terpasang secara permanen pada obj, tidak peduli bagaimana cara penggunaannya. Ini bisa berguna di dalam kelas ketika Anda perlu mempertahankan this bahkan jika suatu metode terlepas.

class Example {
constructor() {
this.handleClick = this.handleClick.bind(this);
}

handleClick() {
console.log(this); // always the instance
}
}

Kelemahan dari metode terikat dan fungsi panah yang digunakan sebagai field instance adalah setiap instance mendapatkan salinan fungsinya sendiri, yang dapat meningkatkan penggunaan memori. Kompromi ini biasanya dapat diterima ketika Anda hanya mengikat sejumlah kecil metode yang sering dilepas, tetapi ini adalah sesuatu yang perlu diperhatikan dalam kode yang sangat penting untuk performa.

Ada juga beberapa kasus khusus warisan di mana this berperilaku berbeda, seperti dalam yang sudah usang with pernyataan. Di dalam a with (obj) { ... } blok, memanggil fungsi yang merupakan properti dari obj pada dasarnya berperilaku seolah-olah Anda telah menulis obj.method(), sehingga this terikat pada objKode modern sebaiknya menghindari hal ini. withNamun, memahami pengecualian ini memperjelas hal tersebut. this Pada dasarnya, hal itu masih bergantung pada bagaimana panggilan fungsi tersebut dibentuk.

Penanganan kejadian sebaris (inline event handler) di HTML juga memiliki aturan khusus: kode penanganan sebaris di sekitarnya melihat this sebagai elemen, tetapi fungsi internal yang didefinisikan di dalam handler tersebut akan kembali ke cara biasa. this aturan. Jadi, fungsi tradisional internal, yang tidak terikat pada apa pun, biasanya akan terlihat. this as globalThis (Atau undefined (dalam mode ketat), bukan elemennya.

Terakhir, ingatlah bahwa fungsi panah tidak memiliki prototype properti dan tidak dapat digunakan sebagai konstruktor dengan new. Mencoba new MyArrow() akan menghasilkan TypeError. Jika Anda memerlukan fungsi yang dapat bertindak sebagai konstruktor, Anda harus menggunakan fungsi biasa atau kelas.

Dengan mengingat detail-detail ini, akan jauh lebih mudah untuk memilih antara fungsi panah dan fungsi tradisional. Gunakan tanda panah di tempat yang Anda inginkan secara leksikal. this dan sintaks yang ringkas, dan kembali ke fungsi reguler kapan pun Anda membutuhkan fungsi dinamis yang digerakkan oleh lokasi pemanggilan. this perilaku atau semantik konstruktor.

Setelah Anda memahami bagaimana this Jika terikat dalam setiap situasi, fungsi panah menjadi sekutu yang ampuh alih-alih sumber bug yang mengejutkan. Mereka menyederhanakan pola umum seperti callback dan transformasi sederhana, sementara fungsi reguler terus menangani peran yang bergantung pada peran mereka sendiri. this pengikatan, seperti metode, konstruktor, dan penanganan kejadian dinamis.

Pos terkait: