Saya perhatikan bahwa tampaknya tidak ada penjelasan yang jelas tentang apa this
kata kunci itu dan bagaimana kata kunci itu benar (dan salah) digunakan dalam JavaScript di situs Stack Overflow.
Saya telah menyaksikan beberapa perilaku yang sangat aneh dengannya dan gagal memahami mengapa hal itu terjadi.
Bagaimana cara this
kerjanya dan kapan harus digunakan?
javascript
this
Maxim Gershkovich
sumber
sumber
this
peter.michaux.ca/articles/javascript-widgets-without-thisthis
kata kunci yang menarik: rainsoft.io/gentle-explanation-of-this-in-javascriptJawaban:
Saya sarankan membaca Mike Barat 's artikel Ruang Lingkup dalam JavaScript ( cermin ) pertama. Ini adalah pengantar yang luar biasa, ramah untuk konsep
this
dan rantai cakupan dalam JavaScript.Setelah Anda mulai terbiasa
this
, aturan sebenarnya cukup sederhana. Standar ECMAScript 5.1 mendefinisikanthis
:Penjilidan ini adalah sesuatu yang dipertahankan oleh penerjemah JavaScript saat mengevaluasi kode JavaScript, seperti register CPU khusus yang menyimpan referensi ke suatu objek. Interpreter memperbarui ThisBinding kapan pun membangun konteks eksekusi dalam satu dari hanya tiga kasus yang berbeda:
1. Konteks eksekusi global awal
Ini adalah kasus untuk kode JavaScript yang dievaluasi di tingkat atas, misalnya ketika langsung di dalam
<script>
:Saat mengevaluasi kode dalam konteks eksekusi global awal, Penjilidan Ini diatur ke objek global,
window
( §10.4.1.1 ).Memasukkan kode eval
... dengan panggilan langsung ke
eval()
ThisBinding dibiarkan tidak berubah; ini adalah nilai yang sama dengan ThisBinding dari konteks eksekusi panggilan ( §10.4.2 (2) (a)).... jika tidak dengan panggilan langsung ke
eval()
ThisBinding diatur ke objek global seolah-olah mengeksekusi dalam konteks eksekusi global awal ( §10.4.2 (1)).
§15.1.2.1.1 mendefinisikan apa panggilan langsung
eval()
itu. Pada dasarnya,eval(...)
adalah panggilan langsung sedangkan sesuatu seperti(0, eval)(...)
atauvar indirectEval = eval; indirectEval(...);
merupakan panggilan tidak langsungeval()
. Lihat jawaban chuckj untuk (1, eval) ('this') vs eval ('this') dalam JavaScript? dan ECMA-262-5 karya Dmitry Soshnikov secara rinci. Bab 2. Mode Ketat. ketika Anda mungkin menggunakaneval()
panggilan tidak langsung .Memasukkan kode fungsi
Ini terjadi ketika memanggil suatu fungsi. Jika fungsi dipanggil pada objek, seperti dalam
obj.myMethod()
atau yang setaraobj["myMethod"]()
, maka Penjilidan Ini diatur ke objek (obj
dalam contoh; §13.2.1 ). Dalam sebagian besar kasus lain, Penjilidan Ini diatur ke objek global ( §10.4.3 ).Alasan untuk menulis "dalam kebanyakan kasus lain" adalah karena ada delapan fungsi built-in ECMAScript 5 yang memungkinkan ThisBinding untuk ditentukan dalam daftar argumen. Fungsi-fungsi khusus ini mengambil apa yang disebut
thisArg
dengan ThisBinding ketika memanggil fungsi ( §10.4.3 ).Fungsi bawaan khusus ini adalah:
Function.prototype.apply( thisArg, argArray )
Function.prototype.call( thisArg [ , arg1 [ , arg2, ... ] ] )
Function.prototype.bind( thisArg [ , arg1 [ , arg2, ... ] ] )
Array.prototype.every( callbackfn [ , thisArg ] )
Array.prototype.some( callbackfn [ , thisArg ] )
Array.prototype.forEach( callbackfn [ , thisArg ] )
Array.prototype.map( callbackfn [ , thisArg ] )
Array.prototype.filter( callbackfn [ , thisArg ] )
Dalam hal
Function.prototype
fungsi, mereka dipanggil pada objek fungsi, tetapi daripada mengatur ThisBinding ke objek fungsi, ThisBinding diatur kethisArg
.Dalam hal
Array.prototype
fungsi, yang diberikancallbackfn
disebut dalam konteks eksekusi di mana ThisBinding diatur kethisArg
jika disediakan; jika tidak, ke objek global.Itulah aturan untuk JavaScript biasa. Ketika Anda mulai menggunakan pustaka JavaScript (mis. JQuery), Anda mungkin menemukan bahwa fungsi pustaka tertentu memanipulasi nilai
this
. Pengembang pustaka JavaScript melakukan ini karena cenderung mendukung kasus penggunaan yang paling umum, dan pengguna perpustakaan biasanya menemukan perilaku ini lebih nyaman. Saat melewati fungsi panggilan balik yang merujukthis
ke fungsi pustaka, Anda harus merujuk ke dokumentasi untuk jaminan apa pun tentang nilai darithis
saat fungsi dipanggil.Jika Anda bertanya-tanya bagaimana perpustakaan JavaScript memanipulasi nilai
this
, perpustakaan hanya menggunakan salah satu fungsi JavaScript bawaan yang menerima athisArg
. Anda juga dapat menulis fungsi Anda sendiri menggunakan fungsi panggilan balik danthisArg
:Ada kasus khusus yang belum saya sebutkan. Saat membuat objek baru melalui
new
operator, penerjemah JavaScript membuat objek baru yang kosong, menetapkan beberapa properti internal, dan kemudian memanggil fungsi konstruktor pada objek baru. Jadi, ketika suatu fungsi dipanggil dalam konteks konstruktor, nilai darithis
adalah objek baru yang dibuat oleh interpreter:Fungsi panah
Fungsi panah (diperkenalkan pada ECMA6) mengubah ruang lingkup
this
. Lihat pertanyaan kanonik yang ada, Deklarasi / ekspresi fungsi vs. fungsi: Apakah setara / dapat dipertukarkan? untuk informasi lebih lanjut. Namun singkatnya:Hanya untuk bersenang-senang, uji pemahaman Anda dengan beberapa contoh
Untuk mengungkapkan jawabannya, arahkan mouse ke kotak abu-abu muda.
Berapa nilai
this
pada baris yang ditandai? Mengapa?Berapakah nilai
this
pada baris yang ditandai saatobj.staticFunction()
dijalankan? Mengapa?Berapa nilai
this
pada baris yang ditandai? Mengapa?Berapa nilai
this
pada baris yang ditandai? Mengapa?Berapa nilai
this
pada baris yang ditandai? Mengapa?sumber
setTimeout
contoh memilikithis
dariwindow(global)
.Kata
this
kunci berperilaku berbeda dalam JavaScript dibandingkan dengan bahasa lain. Dalam bahasa Berorientasi Objek,this
kata kunci mengacu pada instance kelas saat ini. Dalam JavaScript nilaithis
ditentukan oleh konteks fungsi invokasi (context.function()
) dan di mana ia disebut.1. Ketika digunakan dalam konteks global
Ketika Anda menggunakan
this
dalam konteks global, itu terikat ke objek global (window
di browser)Ketika Anda menggunakan
this
di dalam suatu fungsi yang didefinisikan dalam konteks global,this
masih terikat pada objek global karena fungsi tersebut sebenarnya merupakan metode konteks global.Di atas
f1
dibuat metode objek global. Dengan demikian kita juga dapat menyebutnya padawindow
objek sebagai berikut:2. Saat digunakan di dalam metode objek
Saat Anda menggunakan
this
kata kunci di dalam metode objek,this
terikat ke objek terlampir "langsung".Di atas saya telah menempatkan kata langsung dalam tanda kutip ganda. Ini untuk membuat titik bahwa jika Anda bersarang objek di dalam objek lain, maka
this
terikat ke induk langsung.Bahkan jika Anda menambahkan fungsi secara eksplisit ke objek sebagai metode, itu masih mengikuti aturan di atas, yang
this
masih menunjuk ke objek induk langsung.3. Saat menjalankan fungsi konteks-kurang
Ketika Anda menggunakan
this
fungsi di dalam yang dipanggil tanpa konteks apa pun (yaitu tidak pada objek apa pun), itu terikat ke objek global (window
di browser) (bahkan jika fungsi tersebut didefinisikan di dalam objek).Mencoba semuanya dengan fungsi
Kita dapat mencoba poin di atas dengan fungsi juga. Namun ada beberapa perbedaan.
this
. untuk menentukannya.new
operator.Di bawah ini saya mencoba semua hal yang kami lakukan dengan Object dan di
this
atas, tetapi dengan terlebih dahulu membuat fungsi alih-alih secara langsung menulis objek.4. Saat digunakan di dalam fungsi konstruktor .
Ketika fungsi digunakan sebagai konstruktor (saat itu disebut dengan
new
kata kunci),this
fungsi tubuh bagian dalam menunjuk ke objek baru yang sedang dibangun.5. Saat digunakan di dalam fungsi yang didefinisikan pada rantai prototipe
Jika metode ini pada rantai prototipe objek,
this
di dalam metode tersebut merujuk ke objek metode dipanggil, seolah-olah metode tersebut didefinisikan pada objek.6. Panggilan dalam (), fungsi berlaku () dan ikat ()
Function.prototype
.this
yang akan digunakan saat fungsi sedang dieksekusi. Mereka juga mengambil parameter apa saja untuk diteruskan ke fungsi asli ketika dipanggil.fun.apply(obj1 [, argsArray])
Tetapkanobj1
sebagai nilaithis
di dalamfun()
dan memanggilfun()
elemen lewatargsArray
sebagai argumennya.fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
- Ditetapkanobj1
sebagai nilai darithis
dalamfun()
dan panggilanfun()
lewatarg1, arg2, arg3, ...
sebagai argumennya.fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
- Mengembalikan referensi ke fungsifun
denganthis
fun di dalam terikatobj1
dan parameterfun
terikat ke parameter yang ditentukanarg1, arg2, arg3,...
.apply
,call
danbind
pasti menjadi jelas.apply
memungkinkan untuk menentukan argumen untuk berfungsi sebagai objek seperti array yaitu objek denganlength
properti numerik dan properti integer non-negatif yang sesuai. Sedangkancall
memungkinkan untuk menentukan argumen ke fungsi secara langsung. Keduanyaapply
dancall
segera memanggil fungsi dalam konteks yang ditentukan dan dengan argumen yang ditentukan. Di sisi lain,bind
cukup mengembalikan fungsi terikat ke nilai yang ditentukanthis
dan argumen. Kami dapat menangkap referensi ke fungsi yang dikembalikan ini dengan menetapkannya ke variabel dan kemudian kami dapat memanggilnya kapan saja.7.
this
dalam event handlerthis
langsung di dalam fungsi penanganan acara mengacu pada elemen yang sesuai. Penugasan fungsi langsung semacam itu dapat dilakukan dengan menggunakanaddeventListener
metode atau melalui metode pendaftaran acara tradisional sepertionclick
.this
langsung di dalam properti acara (seperti<button onclick="...this..." >
) elemen, itu merujuk ke elemen.this
secara tidak langsung melalui fungsi lain yang disebut di dalam fungsi penanganan acara atau properti acara diselesaikan ke objek globalwindow
.attachEvent
. Alih-alih menugaskan fungsi ke pengendali acara (dan dengan demikian membuat metode fungsi elemen), ia memanggil fungsi pada acara tersebut (secara efektif memanggilnya dalam konteks global).Saya merekomendasikan untuk mencoba ini dengan lebih baik di JSFiddle .
8.
this
dalam fungsi panah ES6Dalam fungsi panah,
this
akan berperilaku seperti variabel umum: itu akan diwarisi dari ruang lingkup leksikalnya. Fungsithis
, di mana fungsi panah didefinisikan, akan menjadi fungsi panahthis
.Jadi, itu perilaku yang sama dengan:
Lihat kode berikut:
sumber
this
tidak ditentukan oleh panggilan. Karena kode tidak dalam mode ketat, nilaithis
harus selalu menjadi objek sehingga default ke objek global. Dan sebenarnya itu sebabnya saya pikir kita bisa langsung melakukan panggilanwindow.f1()
, sehingga berartif1()
sudah terlampir padawindow
objek, maksud saya sebelum doa. Apakah saya salah?window.fn
, yang bukan. ini default ke objek global karena tidak ada referensi dasar yang digunakan dalam panggilan, bukan karena di mana fungsi didefinisikan (jadi ini masih diatur oleh bagaimana fungsi dipanggil). Jika Anda secara eksplisit menyebutnya menggunakanwindow.fn
, maka Anda mengatur ini ke jendela . Hasil yang sama, cara yang berbeda untuk melakukannya. :-)Javascript
this
Doa fungsi sederhana
Pertimbangkan fungsi berikut:
Perhatikan bahwa kami menjalankan ini dalam mode normal, yaitu mode ketat tidak digunakan.
Saat berjalan di browser, nilai
this
akan dicatat sebagaiwindow
. Ini karenawindow
merupakan variabel global dalam cakupan browser web.Jika Anda menjalankan bagian kode yang sama di lingkungan seperti node.js,
this
akan merujuk ke variabel global di aplikasi Anda.Sekarang jika kita menjalankan ini dalam mode ketat dengan menambahkan pernyataan
"use strict";
ke awal deklarasi fungsi,this
tidak akan lagi merujuk ke variabel global di salah satu lingkungan. Ini dilakukan untuk menghindari kebingungan dalam mode ketat.this
akan, dalam hal ini hanya loginundefined
, karena memang seperti itu, tidak didefinisikan.Dalam kasus berikut, kita akan melihat bagaimana memanipulasi nilai
this
.Memanggil fungsi pada objek
Ada berbagai cara untuk melakukan ini. Jika Anda telah memanggil metode asli dalam Javascript seperti
forEach
danslice
, Anda harus sudah tahu bahwathis
variabel dalam kasus itu merujukObject
pada yang Anda panggil fungsi itu (Perhatikan bahwa dalam javascript, hampir semua adalahObject
, termasukArray
s danFunction
s). Ambil kode berikut sebagai contoh.Jika suatu
Object
berisi properti yang menyimpan aFunction
, properti itu disebut metode. Metode ini, ketika dipanggil, akan selalu memilikithis
set variabel untukObject
dikaitkan dengan itu. Ini berlaku untuk mode ketat dan non-ketat.Perhatikan bahwa jika suatu metode disimpan (atau lebih tepatnya, disalin) dalam variabel lain, referensi ke
this
tidak lagi dipertahankan dalam variabel baru. Sebagai contoh:Mempertimbangkan skenario yang lebih umum:
Kata
new
kunciPertimbangkan fungsi konstruktor dalam Javascript:
Bagaimana cara kerjanya? Baiklah, mari kita lihat apa yang terjadi ketika kita menggunakan
new
kata kunci.new
kata kunci akan segera menginisialisasiObject
tipePerson
.Object
mengatur konstruktornyaPerson
. Juga, perhatikan bahwa hanyatypeof awal
akan kembaliObject
.Object
akan diberi prototipePerson.prototype
. Ini berarti bahwa setiap metode atau properti dalamPerson
prototipe akan tersedia untuk semua kejadianPerson
, termasukawal
.Person
itu sendiri sekarang dipanggil;this
menjadi referensi ke objek yang baru dibangunawal
.Cukup mudah, eh?
Perhatikan bahwa spesifikasi ECMAScript resmi tidak menyatakan bahwa jenis fungsi tersebut adalah
constructor
fungsi sebenarnya . Mereka hanya fungsi normal, dannew
dapat digunakan pada fungsi apa pun. Hanya saja kami menggunakannya seperti itu, dan kami menyebutnya begitu saja.Memanggil fungsi pada Fungsi:
call
danapply
Jadi ya, karena
function
s jugaObjects
(dan sebenarnya variabel kelas pertama dalam Javascript), bahkan fungsi memiliki metode yang ... yah, fungsi itu sendiri.Semua fungsi mewarisi dari global
Function
, dan dua dari banyak metodenya adalahcall
danapply
, dan keduanya dapat digunakan untuk memanipulasi nilaithis
dalam fungsi yang mereka panggil.Ini adalah contoh khas penggunaan
call
. Ini pada dasarnya mengambil parameter pertama dan menetapkanthis
fungsifoo
sebagai referensithisArg
. Semua parameter lain yang diteruskan kecall
diteruskan ke fungsifoo
sebagai argumen.Jadi kode di atas akan masuk
{myObj: "is cool"}, [1, 2, 3]
konsol. Cara yang cukup bagus untuk mengubah nilaithis
dalam fungsi apa pun.apply
hampir sama dengancall
accept yang hanya membutuhkan dua parameter:thisArg
dan array yang berisi argumen untuk diteruskan ke fungsi. Jadicall
panggilan di atas dapat diterjemahkan menjadiapply
seperti ini:Catat itu
call
danapply
dapat menimpa nilaithis
set oleh metode titik yang kita bahas dalam butir kedua. Cukup sederhana :)Mempresentasikan ....
bind
!bind
adalah saudara daricall
danapply
. Ini juga merupakan metode yang diwarisi oleh semua fungsi dariFunction
konstruktor global di Javascript. Perbedaan antarabind
dancall
/apply
adalah keduanyacall
danapply
akan benar-benar memanggil fungsi.bind
, di sisi lain, mengembalikan fungsi baru denganthisArg
danarguments
sebelumnya. Mari kita ambil contoh untuk lebih memahami ini:Lihat perbedaan antara ketiganya? Itu halus, tetapi mereka digunakan secara berbeda. Sukai
call
danapply
,bind
juga akan menunggangi nilaithis
set oleh metode dot-method.Perhatikan juga bahwa tidak satu pun dari ketiga fungsi ini melakukan perubahan pada fungsi aslinya.
call
danapply
akan mengembalikan nilai dari fungsi yang baru dibangun sementarabind
akan mengembalikan fungsi yang baru dibangun itu sendiri, siap dipanggil.Barang ekstra, salin ini
Terkadang, Anda tidak suka fakta yang
this
berubah dengan cakupan, terutama cakupan bersarang. Lihatlah contoh berikut.Dalam kode di atas, kita melihat bahwa nilai
this
berubah dengan cakupan bersarang, tetapi kami menginginkan nilai darithis
lingkup asli. Jadi kami 'menyalin'this
kethat
dan menggunakan salinannya sebagai gantithis
. Pintar, eh?Indeks:
this
secara default?new
kata kunci?this
dengancall
danapply
?bind
.this
untuk memecahkan masalah ruang lingkup bersarang.sumber
"Ini" adalah tentang ruang lingkup. Setiap fungsi memiliki cakupannya sendiri, dan karena segala sesuatu di JS adalah objek, bahkan fungsi dapat menyimpan beberapa nilai ke dalam dirinya sendiri menggunakan "ini". OOP 101 mengajarkan bahwa "ini" hanya berlaku untuk instance objek. Oleh karena itu, setiap kali fungsi dijalankan, "instance" baru dari fungsi tersebut memiliki arti baru "ini".
Kebanyakan orang menjadi bingung ketika mereka mencoba menggunakan "ini" di dalam fungsi penutupan anonim seperti:
Jadi di sini, di dalam setiap (), "ini" tidak memiliki "nilai" yang Anda harapkan (dari
diatasnya). Jadi, untuk mengatasi masalah ini (tidak ada permainan kata-kata), pengembang dapat:Cobalah; Anda akan mulai menyukai pola pemrograman ini
sumber
this
kunci tidak ada hubungannya dengan ruang lingkup. Selain itu, ia memiliki arti juga dalam fungsi-fungsi yang bukan properti objek.this
tidak SEMUA tentang ruang lingkup. Ini adalah SEMUA tentang konteks eksekusi, yang tidak sama dengan ruang lingkup. JavaScript dibatasi secara leksikal (ruang lingkup makna ditentukan oleh lokasi kode), tetapithis
ditentukan oleh bagaimana fungsi yang memuatnya dipanggil - bukan di mana fungsi itu berada.Karena utas ini telah meningkat, saya telah mengumpulkan beberapa poin untuk pembaca yang baru dalam
this
topik.Bagaimana nilai
this
ditentukan?Kami menggunakan ini mirip dengan cara kami menggunakan kata ganti dalam bahasa alami seperti bahasa Inggris: "John berlari cepat karena ia mencoba untuk naik kereta." Sebaliknya kita bisa menulis "... John sedang mencoba untuk menangkap kereta".
this
tidak diberi nilai sampai suatu objek memanggil fungsi di mana ia didefinisikan. Dalam lingkup global, semua variabel dan fungsi global didefinisikan padawindow
objek. Oleh karena itu,this
dalam fungsi global mengacu pada (dan memiliki nilai)window
objek global .Ketika
use strict
,this
dalam fungsi global dan anonim yang tidak terikat pada objek apa pun memegang nilaiundefined
.Kata
this
kunci paling disalahpahami ketika: 1) kami meminjam metode yang menggunakanthis
, 2) kami menetapkan metode yang digunakanthis
untuk variabel, 3) fungsi yang digunakanthis
dilewatkan sebagai fungsi panggilan balik, dan 4)this
digunakan di dalam penutupan - fungsi batin. (2)Apa yang memegang masa depan
Didefinisikan dalam ECMA Script 6 , fungsi panah mengadopsi
this
pengikatan dari lingkup melampirkan (fungsi atau global).Sementara fungsi panah memberikan alternatif untuk digunakan
bind()
, penting untuk dicatat bahwa mereka pada dasarnya menonaktifkanthis
mekanisme tradisional demi pelingkupan leksikal yang lebih luas dipahami. (1)Referensi:
sumber
this
dalam JavaScript selalu mengacu pada 'pemilik' fungsi yang sedang dijalankan .Jika tidak ada pemilik eksplisit yang didefinisikan, maka pemilik paling atas, objek jendela, direferensikan.
Jadi jika saya lakukan
element.onclick = someKindOfFunction;
this
akan merujuk ke objek elemen. Tapi hati-hati, banyak orang membuat kesalahan ini.<element onclick="someKindOfFunction()">
Dalam kasus terakhir, Anda hanya mereferensikan fungsi, bukan menyerahkannya ke elemen. Karena itu,
this
akan merujuk ke objek jendela.sumber
Setiap konteks eksekusi di javascript memiliki parameter ini yang ditetapkan oleh:
eval
Anda dapat mengatur nilai ini menggunakan
func.call
,func.apply
ataufunc.bind
.Secara default, dan apa yang membingungkan kebanyakan pemula, ketika pendengar disebut setelah acara dimunculkan pada elemen DOM, yang ini nilai fungsi adalah elemen DOM.
jQuery membuat ini sepele untuk berubah dengan jQuery.proxy.
sumber
this
Javascript adalah bahwa itu bukan properti intrinsik dari fungsi itu sendiri, tetapi lebih merupakan artefak dari cara fungsi dipanggil.func.call
,func.bind
dll. - Sushilthis
tidak tidak referensi lingkup fungsi ini.this
akan mereferensikan objek tertentu (atau mungkinundefined
), yang seperti telah Anda katakan dapat diubah menggunakan.call()
atau.apply()
. Ruang lingkup fungsi adalah (pada dasarnya, ketika disederhanakan) variabel mana yang memiliki akses, dan ini sepenuhnya tergantung pada di mana fungsi tersebut dinyatakan dan tidak dapat diubah.this
dan ruang lingkup tidak ada hubungannya sama sekali dalam ES5 dan sebelumnya (misalnya, ketika jawaban ini ditulis). Dalam ES2015 (alias ES6),this
dan lingkup terkait satu cara panah wrt cara yang cukup minimal (fungsi panahthis
dalam diwarisi dari cakupan melampirkan), tetapithis
tidak pernah merujuk pada lingkup.Berikut adalah salah satu sumber
this
masuk yang bagusJavaScript
.Berikut ringkasannya:
global ini
Di browser, di lingkup global,
this
adalahwindow
objekDalam
node
menggunakan repl,this
adalah namespace teratas. Anda dapat menyebutnya sebagaiglobal
.Dalam
node
mengeksekusi dari skrip,this
di lingkup global dimulai sebagai objek kosong. Ini tidak sama denganglobal
berfungsi ini
Kecuali dalam hal event handler DOM atau ketika
thisArg
disediakan (lihat lebih jauh ke bawah), baik di node maupun di browser yang menggunakanthis
fungsi yang tidak disebut dengannew
referensi lingkup global ...Jika Anda menggunakan
use strict;
, dalam halthis
apaundefined
Jika Anda memanggil fungsi dengan
new
yangthis
akan menjadi konteks baru, itu tidak akan referensi globalthis
.Fungsi yang Anda buat menjadi objek fungsi. Mereka secara otomatis mendapatkan
prototype
properti khusus , yang merupakan sesuatu yang dapat Anda berikan nilainya. Saat Anda membuat instance dengan memanggil fungsinew
Anda dengan Anda mendapatkan akses ke nilai yang Anda tetapkan untukprototype
properti. Anda mengakses nilai-nilai itu menggunakanthis
.Biasanya merupakan kesalahan untuk menetapkan array atau objek pada
prototype
. Jika Anda ingin instance untuk masing-masing memiliki array sendiri, buat mereka dalam fungsi, bukan prototipe.Anda dapat menggunakan
this
fungsi apa pun pada objek untuk merujuk ke properti lain pada objek itu. Ini tidak sama dengan instance yang dibuat dengannew
.Dalam penangan acara HTML DOM,
this
selalu ada referensi ke elemen DOM tempat acara dilampirkanKecuali Anda
bind
konteksnyaDi dalam atribut HTML di mana Anda dapat menempatkan JavaScript,
this
adalah referensi ke elemen.Anda dapat menggunakannya
eval
untuk mengaksesthis
.Anda dapat menggunakan
with
untuk menambahthis
ruang lingkup saat ini untuk membaca dan menulis ke nilaithis
tanpa merujukthis
secara eksplisit.jQuery akan di banyak tempat
this
merujuk ke elemen DOM.sumber
Daniel, penjelasan yang luar biasa! Beberapa kata pada ini dan daftar yang baik dari
this
pointer konteks eksekusi dalam hal penangan acara.Dalam dua kata,
this
dalam JavaScript menunjukkan objek dari siapa (atau dari konteks pelaksanaannya) fungsi saat ini dijalankan dan selalu hanya baca, Anda tetap tidak dapat mengaturnya (upaya tersebut akan berakhir dengan 'Kiri tidak valid' sisi dalam pesan tugas.Untuk penangan event: penangan event inline, seperti
<element onclick="foo">
, mengesampingkan penangan lain yang terlampir sebelumnya dan sebelumnya, jadi berhati-hatilah dan lebih baik untuk tidak ikut serta dalam delegasi acara inline sama sekali. Dan terima kasih kepada Zara Alaverdyan yang mengilhami saya untuk daftar contoh ini melalui debat yang berbeda :)el.onclick = foo; // in the foo - obj
el.onclick = function () {this.style.color = '#fff';} // obj
el.onclick = function() {doSomething();} // In the doSomething - Window
el.addEventListener('click',foo,false) // in the foo - obj
el.attachEvent('onclick, function () { // this }') // window, all the compliance to IE :)
<button onclick="this.style.color = '#fff';"> // obj
<button onclick="foo"> // In the foo - window, but you can <button onclick="foo(this)">
sumber
Ada banyak kebingungan mengenai bagaimana kata kunci "ini" ditafsirkan dalam JavaScript. Semoga artikel ini akan meletakkan semua orang untuk beristirahat sekali dan untuk semua. Dan masih banyak lagi. Silakan baca seluruh artikel dengan seksama. Diperingatkan bahwa artikel ini panjang.
Terlepas dari konteks di mana ia digunakan, "ini" selalu merujuk "objek saat ini" dalam Javascript. Namun, apa "objek saat ini" berbeda menurut konteksnya . The konteks mungkin persis 1 dari 6 berikut:
Berikut ini menjelaskan masing-masing konteks ini satu per satu:
Konteks Global (yaitu Di luar semua fungsi):
Di luar semua fungsi (yaitu dalam konteks global) "objek saat ini" (dan karenanya nilai "ini" ) selalu menjadi objek "jendela" untuk browser.
Panggilan "Non Bound Function" Langsung Di Dalam :
Di dalam Panggilan "Fungsi Tidak Terikat" Langsung, objek yang memanggil pemanggilan fungsi menjadi "objek saat ini" (dan karenanya nilai "ini" ). Jika suatu fungsi dipanggil tanpa objek saat ini eksplisit , objek saat ini adalah objek "jendela" (Untuk Mode Non Strict) atau tidak terdefinisi (Untuk Mode Strict). Setiap fungsi (atau variabel) yang didefinisikan dalam Konteks Global secara otomatis menjadi properti dari objek "jendela". Misalnya, fungsi Misalkan didefinisikan dalam Konteks Global sebagai
itu menjadi properti objek jendela, seolah-olah Anda telah mendefinisikannya sebagai
Dalam "Non Strict Mode", Memanggil / Memanggil fungsi ini langsung melalui "UserDefinedFunction ()" akan secara otomatis memanggil / memanggilnya sebagai "window.UserDefinedFunction ()" menjadikan "jendela" sebagai "objek saat ini" (dan karenanya nilai dari " ini " ) dalam " UserDefinedFunction " .Melakukan fungsi ini dalam" Non Strict Mode "akan menghasilkan yang berikut ini
Dalam "Mode Ketat", Memanggil / Memanggil fungsi langsung melalui "UserDefinedFunction ()" akan "TIDAK" secara otomatis memanggil / memanggilnya sebagai "window.UserDefinedFunction ()" .Dari "objek saat ini" (dan nilai "ini" ) dalam "UserDefinedFunction" harus ditentukan . Menjalankan fungsi ini dalam "Mode Ketat" akan menghasilkan yang berikut ini
Namun, menjalankannya secara eksplisit menggunakan objek jendela akan menghasilkan sebagai berikut
Mari kita lihat contoh lain. Silakan lihat kode berikut
Dalam contoh di atas kita melihat bahwa ketika "UserDefinedFunction" dipanggil melalui o1 , "this" mengambil nilai o1 dan nilai propertinya "a" dan "b" ditampilkan. Nilai "c" dan "d" ditampilkan sebagai tidak terdefinisi karena o1 tidak mendefinisikan properti ini
Demikian pula ketika "UserDefinedFunction" itu dipanggil melalui o2 , "ini" mengambil nilai o2 dan nilai properti nya "c" dan "d" mendapatkan tampil pada display nilai "a" dan "b" yang ditampilkan sebagai terdefinisi sebagai o2 tidak tidak mendefinisikan properti ini.
Di dalam Indirect "Non Bound Function" Panggil melalui functionName.call dan functionName.apply :
Ketika "Fungsi Tidak Terikat" dipanggil melalui functionName.call atau functionName.apply , "objek saat ini" (dan karenanya nilai "ini" ) diatur ke nilai parameter "ini" (parameter pertama) diteruskan untuk memanggil Saya melamar . Kode berikut menunjukkan hal yang sama.
Kode di atas dengan jelas menunjukkan bahwa nilai "ini" untuk "Fungsi NON Bound" apa pun dapat diubah melalui panggilan / berlaku . Juga, jika parameter "ini" tidak secara eksplisit diteruskan untuk memanggil / menerapkan , "objek saat ini" (dan karenanya nilai "ini") diatur ke "jendela" dalam mode Non-ketat dan "tidak terdefinisi" dalam mode ketat.
Di dalam Panggilan "Fungsi Terikat" (yaitu fungsi yang telah terikat dengan memanggil functionName.bind ):
Fungsi terikat adalah fungsi yang nilainya "ini" telah diperbaiki. Kode berikut menunjukkan bagaimana "ini" bekerja jika ada fungsi terikat
Seperti yang diberikan dalam kode di atas, nilai "ini" untuk "Fungsi Batas" apa pun TIDAK DAPAT diubah melalui panggilan / berlaku . Juga, jika parameter "ini" tidak secara eksplisit diteruskan untuk mengikat, "objek saat ini" (dan karenanya nilai "ini" ) diatur ke "jendela" dalam mode Non-ketat dan "tidak terdefinisi" dalam mode ketat. Satu hal lagi. Mengikat fungsi yang sudah terikat tidak mengubah nilai "ini" . Tetap ditetapkan sebagai nilai yang ditetapkan oleh fungsi bind pertama.
Sedangkan Pembuatan Objek melalui "baru" :
Di dalam fungsi konstruktor, "objek saat ini" (dan karenanya nilai "ini" ) merujuk objek yang saat ini sedang dibuat melalui "baru" terlepas dari status mengikat fungsi. Namun jika konstruktor adalah fungsi terikat, ia harus dipanggil dengan seperangkat argumen yang telah ditentukan sebagaimana ditetapkan untuk fungsi terikat.
Pengendali acara DOM Inside Inline :
Silakan lihat Cuplikan HTML berikut
The "ini" di contoh di atas merujuk pada "tombol" elemen dan "div" elemen masing-masing.
Pada contoh pertama, warna font tombol harus diatur ke putih ketika diklik.
Dalam contoh kedua ketika elemen "div" diklik, ia akan memanggil fungsi OnDivClick dengan parameter keduanya merujuk pada elemen div yang diklik. Namun nilai "ini" dalam OnDivClick TIDAK AKAN mereferensikan elemen div yang diklik . Ini harus ditetapkan sebagai "objek jendela" atau "tidak terdefinisi" dalam Mode Non-ketat dan Ketat masing-masing (jika OnDivClick adalah fungsi tidak terikat ) atau diatur ke nilai Batas yang ditentukan sebelumnya (jika OnDivClick adalah fungsi terikat )
Berikut ini ringkasan seluruh artikel
Global Context "ini" selalu mengacu pada "jendela" objek
Setiap kali suatu fungsi dipanggil, ia dipanggil dalam konteks objek ( "objek saat ini" ). Jika objek saat ini tidak disediakan secara eksplisit, objek saat ini adalah "objek jendela" dalam Mode NON Ketat dan "tidak terdefinisi" dalam Mode Ketat secara default.
Nilai "ini" dalam fungsi Non Bound adalah referensi ke objek dalam konteks fungsi yang dipanggil ( "objek saat ini" )
Nilai "ini" dalam fungsi Non Bound dapat diganti dengan panggilan dan menerapkan metode fungsi.
Nilai "ini" adalah tetap untuk fungsi Terikat dan tidak dapat diganti dengan panggilan dan menerapkan metode fungsi.
Binding dan fungsi yang sudah terikat tidak mengubah nilai "ini". Tetap ditetapkan sebagai nilai yang ditetapkan oleh fungsi bind pertama.
Nilai "ini" dalam konstruktor adalah objek yang sedang dibuat dan diinisialisasi
Nilai "ini" dalam event handler DOM inline adalah referensi ke elemen yang event handler diberikan.
sumber
Mungkin artikel yang paling terperinci dan komprehensif
this
adalah sebagai berikut:Penjelasan lembut tentang kata kunci 'ini' dalam JavaScript
Gagasan di belakang
this
adalah untuk memahami bahwa jenis pemanggilan fungsi memiliki kepentingan yang signifikan pada pengaturanthis
nilai.Ketika mengalami kesulitan mengidentifikasi
this
, jangan bertanya pada diri sendiri:tapi jangan bertanya pada diri sendiri:
Untuk fungsi panah (kasus khusus transparansi konteks) tanyakan pada diri sendiri:
Pola pikir ini benar ketika berhadapan dengan
this
dan akan menyelamatkan Anda dari sakit kepala.sumber
this
kata kunci?Ini adalah penjelasan terbaik yang pernah saya lihat: Memahami JavaScripts ini dengan Clarity
Ada Empat Skenario di mana ini bisa membingungkan:
Dia memberikan contoh kode, penjelasan, dan solusi, yang saya pikir sangat membantu.
sumber
Dalam istilah pseudoklasik, cara banyak kuliah mengajarkan kata kunci 'ini' adalah sebagai objek yang dipakai oleh kelas atau konstruktor objek. Setiap kali sebuah objek baru dibangun dari sebuah kelas, bayangkan bahwa di bawah kap sebuah instance lokal dari objek 'ini' dibuat dan dikembalikan. Saya ingat itu diajarkan seperti ini:
sumber
this
adalah salah satu konsep disalahpahami dalam JavaScript karena berperilaku sedikit berbeda dari satu tempat ke tempat lain. Sederhananya,this
mengacu pada "pemilik" fungsi yang sedang kami jalankan .this
membantu mendapatkan objek saat ini (alias konteks eksekusi) yang kami kerjakan. Jika Anda mengerti di objek mana fungsi saat ini dieksekusi, Anda dapat dengan mudah memahami apa itu saatthis
iniDi atas kita membuat 3 variabel dengan nama yang sama 'val'. Satu dalam konteks global, satu di dalam obj dan yang lainnya di dalam metode obj. JavaScript menyelesaikan pengidentifikasi dalam konteks tertentu dengan meningkatkan rantai lingkup dari lokal go global.
Beberapa tempat di mana
this
dapat dibedakanMemanggil metode objek
Ketika line1 dieksekusi, JavaScript menetapkan konteks eksekusi (EC) untuk pemanggilan fungsi, mengatur
this
ke objek yang dirujuk oleh apa pun yang datang sebelum "" terakhir. . jadi di baris terakhir Anda bisa mengerti yanga()
dieksekusi dalam konteks global yang manawindow
.Dengan Konstruktor
this
dapat digunakan untuk merujuk ke objek yang sedang dibuatKetika baru
Person()
dieksekusi, objek yang sama sekali baru dibuat.Person
dipanggil danthis
diatur untuk referensi objek baru itu.Panggilan fungsi
Jika kami kehilangan
new
kata kunci,whatIsThis
lihat konteks paling global yang dapat ditemukannya (window
)Dengan penangan acara
Jika pengendali event inline,
this
merujuk ke objek globalSaat menambahkan pengendali acara melalui JavaScript,
this
merujuk ke elemen DOM yang menghasilkan acara..apply()
.call()
dan.bind()
var that = this
artinya dalam JavaScriptsumber
Nilai "ini" tergantung pada "konteks" di mana fungsi dijalankan. Konteksnya dapat berupa objek apa pun atau objek global, yaitu jendela.
Jadi Semantik "ini" berbeda dari bahasa OOP tradisional. Dan itu menyebabkan masalah: 1. ketika suatu fungsi dilewatkan ke variabel lain (kemungkinan besar, panggilan balik); dan 2. ketika penutupan dipanggil dari metode anggota kelas.
Dalam kedua kasus, ini diatur ke jendela.
sumber
Apa ini bisa membantu? (Sebagian besar kebingungan 'ini' dalam javascript berasal dari fakta bahwa umumnya ini tidak terkait dengan objek Anda, tetapi ke lingkup eksekusi saat ini - yang mungkin tidak persis bagaimana cara kerjanya tetapi selalu terasa seperti itu bagi saya - lihat artikel untuk penjelasan lengkap)
sumber
Sedikit info tentang kata kunci ini
Mari masuk
this
kata kunci ke konsol dalam lingkup global tanpa kode apa pun kecualiDi Klien / Browser
this
kata kunci adalah objek global yangwindow
dan
Dalam kata kunci runtime Server / Node / Javascript
this
juga merupakan objek global yangmodule.exports
Perlu diingat
exports
hanyalah referensi untukmodule.exports
sumber
ini digunakan untuk Lingkup seperti ini
nilai txt1 dan txt sama dalam contoh di atas $ (ini) = $ ('# tbleName tbody tr') adalah Sama
sumber
Saya memiliki pandangan berbeda
this
dari jawaban lain yang saya harap dapat membantu.Salah satu cara untuk melihat JavaScript adalah dengan melihat bahwa hanya ada 1 cara untuk memanggil fungsi 1 . ini
Selalu ada beberapa nilai yang diberikan untuk
objectForThis
.Yang lainnya adalah gula sintaksis
functionObject.call
Jadi, semua hal lain dapat dijelaskan dengan bagaimana ia diterjemahkan
functionObject.call
.Jika Anda hanya memanggil fungsi maka
this
adalah "objek global" yang di browser adalah jendelaDengan kata lain,
secara efektif diterjemahkan ke dalam
Perhatikan bahwa jika Anda menggunakan mode ketat maka
this
akan menjadiundefined
yang berarti
Dengan kata lain,
secara efektif diterjemahkan ke dalam
Dalam JavaScript ada operator seperti
+
dan-
dan*
. Ada juga operator titik yang.
The
.
Operator bila digunakan dengan fungsi di sebelah kanan dan objek di sebelah kiri secara efektif berarti "lulus objek sebagaithis
fungsi.Contoh
Dengan kata lain
bar.foo()
diterjemahkan menjadiconst temp = bar.foo; temp.call(bar);
Perhatikan bahwa tidak masalah bagaimana fungsi itu dibuat (kebanyakan ...). Semua ini akan menghasilkan hasil yang sama
Sekali lagi ini semua hanyalah gula sintaksis
Satu kerutan lainnya adalah rantai prototipe. Ketika Anda menggunakan
a.b
JavaScript, pertama-tama terlihat pada objek yang dirujuk langsung oleha
untuk propertib
. Jikab
tidak ditemukan pada objek maka JavaScript akan mencari prototipe objek untuk ditemukanb
.Ada berbagai cara untuk mendefinisikan prototipe objek, yang paling umum pada 2019 adalah
class
kata kunci. Untuk tujuanthis
meskipun tidak masalah. Yang penting adalah bahwa ketika terlihat di objeka
untuk propertib
jika menemukan propertib
pada objek atau dalam rantai prototipe itu jikab
akhirnya menjadi fungsi maka aturan yang sama seperti di atas berlaku.b
Referensi fungsi akan dipanggil menggunakancall
metode dan lewata
sebagai objectForThis seperti yang ditunjukkan bagian atas jawaban ini.Sekarang. Mari kita bayangkan kita membuat fungsi yang secara eksplisit mengatur
this
sebelum memanggil fungsi lain dan kemudian memanggilnya dengan.
operator (titik)Setelah terjemahan yang digunakan
call
,obj.bar()
menjadiconst temp = obj.bar; temp.call(obj);
. Ketika kita memasukibar
fungsi yang kita panggilfoo
tetapi kita secara eksplisit melewati objek lain untuk objectForThis sehingga ketika kita tiba di foothis
adalah objek batin itu.Inilah yang keduanya
bind
dan=>
fungsi lakukan secara efektif. Mereka lebih banyak gula sintaksis. Mereka secara efektif membangun fungsi tak kasat mata baru persis seperti dibar
atas yang secara eksplisit mengaturthis
sebelum memanggil fungsi apa pun yang ditentukan. Dalam hal mengikatthis
diatur ke apa pun yang Anda lewatibind
.Perhatikan bahwa jika
functionObject.bind
tidak ada kita bisa membuat sendiri seperti inidan kemudian kita bisa menyebutnya seperti ini
Fungsi panah,
=>
operator adalah gula sintaksis untuk mengikatsama dengan
Sama seperti
bind
, fungsi tak terlihat baru dibuat yang memanggil fungsi yang diberikan dengan nilai terikat untukobjectForThis
tetapi tidak sepertibind
objek yang akan terikat adalah implisit. Apa pun yangthis
terjadi ketika=>
operator digunakan.Jadi, sama seperti aturan di atas
obj.foo()
menerjemahkanconst temp = obj.foo; temp.call(obj);
yang berarti operator panah di dalamfoo
akan mengikatobj
ke fungsi tak terlihat baru dan mengembalikan fungsi tak terlihat baru yang ditugaskanb
.b()
akan berfungsi seperti biasab.call(window)
ataub.call(undefined)
memanggil fungsi tak terlihat yangfoo
dibuat. Fungsi tak terlihat itu mengabaikan yangthis
diteruskan ke dalamnya dan meneruskanobj
sebagai objectForThis` ke fungsi panah.Kode di atas diterjemahkan menjadi
1
apply
adalah fungsi lain yang mirip dengancall
Tetapi pada ES6 secara konseptual Anda bahkan dapat menerjemahkannya menjadi
sumber
Ringkasan
this
Javascript:this
ditentukan oleh bagaimana fungsi dipanggil bukan, di mana ia dibuat!this
ditentukan oleh Obyek yang tersisa dari titik. (window
di ruang global)this
mengacu pada elemen DOM yang menjadi dasar acara tersebut.new
kata kunci nilaithis
merujuk ke objek yang baru dibuatthis
dengan fungsi:call
,apply
,bind
Contoh:
Contoh pendengar acara:
Contoh konstruktor:
sumber
Untuk memahami "ini" dengan benar orang harus memahami konteks dan ruang lingkup dan perbedaan di antara mereka.
Lingkup : Dalam lingkup javascript terkait dengan visibilitas variabel, ruang lingkup dicapai melalui penggunaan fungsi. (Baca lebih lanjut tentang ruang lingkup)
Konteks : Konteks terkait dengan objek. Ini merujuk ke objek yang memiliki fungsi. Saat Anda menggunakan kata kunci JavaScript "this", ini merujuk ke objek yang memiliki fungsi. Misalnya, di dalam suatu fungsi, ketika Anda mengatakan: "this.accoutNumber", Anda merujuk ke properti "accoutNumber", yang menjadi milik objek yang memiliki fungsi itu.
Jika objek "myObj" memiliki metode yang disebut "getMyName", ketika kata kunci JavaScript "this" digunakan di dalam "getMyName", itu merujuk ke "myObj". Jika fungsi "getMyName" dieksekusi dalam lingkup global, maka "ini" merujuk ke objek jendela (kecuali dalam mode ketat).
Sekarang mari kita lihat beberapa contoh:
Runnig abobve kode dalam output browser akan:
Menurut output Anda berada di dalam konteks objek jendela, juga terlihat bahwa prototipe jendela mengacu pada Objek.
Sekarang mari kita coba bagian dalam suatu fungsi:
Keluaran:
Outputnya sama karena kami mencatat variabel 'ini' di lingkup global dan kami mencatatnya di lingkup fungsional, kami tidak mengubah konteksnya. Dalam kedua kasus konteksnya sama, terkait dengan objek janda .
Sekarang mari kita buat objek kita sendiri. Dalam javascript, Anda dapat membuat objek dengan banyak cara.
Keluaran:
Jadi dari contoh di atas, kami menemukan bahwa kata kunci 'ini' mengacu pada konteks baru yang terkait dengan myObj, dan myObject juga memiliki rantai prototipe ke Object.
Mari kita lempar contoh lain:
keluaran: Masuk akal bukan? (baca komentar)
Jika Anda kesulitan memahami contoh di atas, mari kita coba dengan panggilan balik kami sendiri;
keluaran:
Sekarang mari kita Memahami Lingkup, Diri, IIFE dan INI bagaimana berperilaku
Outputnya cukup luar biasa bukan?
sumber
Jawaban sederhana:
Kata kunci "ini" selalu tergantung pada konteks doa. Mereka disebutkan di bawah ini.
FUNGSI DISEBUT DENGAN KATA KUNCI BARU
Jika fungsinya dipanggil dengan kata kunci BARU maka INI akan terikat pada objek yang baru dibuat.
Di atas ini akan terikat ke objek 'myCar'
FUNGSI DISEBUT SECARA EKSPLISIT MENGGUNAKAN METODE PANGGILAN DAN APLIKASI.
Dalam hal ini, INI akan terikat pada objek yang secara eksplisit diteruskan ke fungsi.
JIKA FUNGSI DISEBUT DENGAN OBYEK SEPENUHNYA KEMUDIAN INI AKAN TERTENTU DENGAN OBYEK YANG
KETIKA FUNGSI DISEBUT TANPA KONTEKS, KEMUDIAN INI AKAN TERTENTU DENGAN OBYEK GLOBAL
DALAM MODE KETAT INI AKAN TIDAK DIKENAL
sumber