Mengapa arguments.callee.caller
properti tersebut tidak lagi digunakan dalam JavaScript?
Itu ditambahkan dan kemudian ditinggalkan dalam JavaScript, tetapi dihilangkan sama sekali oleh ECMAScript. Beberapa browser (Mozilla, IE) selalu mendukungnya dan tidak memiliki rencana pada peta untuk menghapus dukungan. Lainnya (Safari, Opera) telah mengadopsi dukungan untuk itu, tetapi dukungan pada browser lama tidak dapat diandalkan.
Apakah ada alasan bagus untuk meletakkan fungsi yang berharga ini dalam keadaan sulit?
(Atau bergantian, apakah ada cara yang lebih baik untuk mengambil pegangan pada fungsi panggilan?)
javascript
ecma262
pcorcoran
sumber
sumber
<b>
dan<i>
kembali (ya, itu sudah usang pada satu titik).Jawaban:
Versi awal JavaScript tidak mengizinkan ekspresi fungsi bernama, dan karena itu kami tidak dapat membuat ekspresi fungsi rekursif:
Untuk menyiasatinya,
arguments.callee
ditambahkan agar kami dapat melakukan:Namun ini sebenarnya solusi yang sangat buruk karena hal ini (dalam hubungannya dengan argumen lain, masalah callee, dan penelepon) membuat inlining dan rekursi ekor menjadi tidak mungkin dalam kasus umum (Anda dapat mencapainya dalam kasus tertentu melalui penelusuran dll, tetapi bahkan kode terbaik tidak optimal karena cek yang tidak diperlukan). Masalah utama lainnya adalah bahwa panggilan rekursif akan mendapatkan
this
nilai yang berbeda , misalnya:Bagaimanapun, EcmaScript 3 menyelesaikan masalah ini dengan mengizinkan ekspresi fungsi bernama, misalnya:
Ini memiliki banyak manfaat:
Fungsi ini dapat dipanggil seperti yang lainnya dari dalam kode Anda.
Itu tidak mencemari namespace.
Nilai
this
tidak berubah.Ini lebih performant (mengakses objek argumen mahal).
Aduh,
Baru menyadari bahwa selain segala sesuatu yang lain pertanyaannya adalah tentang
arguments.callee.caller
, atau lebih khususFunction.caller
.Kapan saja Anda dapat menemukan penelepon terdalam dari fungsi apa pun di stack, dan seperti yang saya katakan di atas, melihat stack panggilan memiliki satu efek utama: Membuat sejumlah besar optimasi tidak mungkin, atau jauh lebih sulit.
Misalnya. jika kami tidak dapat menjamin bahwa suatu fungsi
f
tidak akan memanggil fungsi yang tidak dikenal, maka itu tidak mungkin untuk sebarisf
. Pada dasarnya itu berarti bahwa setiap situs panggilan yang mungkin tidak dapat ditelusuri secara sepele mengakumulasi sejumlah besar penjaga, ambil:Jika juru bahasa js tidak dapat menjamin bahwa semua argumen yang disediakan adalah angka pada saat panggilan dilakukan, maka perlu memasukkan cek untuk semua argumen sebelum kode yang diuraikan, atau tidak dapat menguraikan fungsi.
Sekarang dalam kasus khusus ini penerjemah pintar harus dapat mengatur ulang cek agar lebih optimal dan tidak memeriksa nilai apa pun yang tidak akan digunakan. Namun dalam banyak kasus itu tidak mungkin dan karena itu menjadi tidak mungkin untuk sebaris.
sumber
this
jadi saya pikir itu tidak relevan dalam hal apakah callee baik atau buruk. Juga, callee dan penelepon hanya "usang" dalam mode ketat (ECMAscript ed 5 Des 2009), tapi saya kira itu tidak diketahui pada 2008 ketika olliej diposting.this
jikathis
ruang lingkup global. Dalam semua kasus lain, nilaithis
akan berubah setelah panggilan rekursif pertama, jadi saya pikir bagian dari jawaban Anda yang mengacu pada pelestarianthis
tidak benar-benar valid.arguments.callee.caller
adalah tidak usang, meskipun tidak membuat penggunaan properti. ( hanya akan memberi Anda referensi ke fungsi saat ini)Function.caller
arguments.callee
Function.caller
, meskipun tidak standar menurut ECMA3, diterapkan di semua browser utama saat ini .arguments.caller
sudah tidak digunakan lagi , dan tidak diterapkan di beberapa peramban utama saat ini (mis. Firefox 3).Function.caller
Jadi situasinya kurang dari ideal, tetapi jika Anda ingin mengakses fungsi panggilan dalam Javascript di semua browser utama, Anda dapat menggunakan properti, baik diakses secara langsung pada referensi fungsi bernama, atau dari dalam fungsi anonim melalui properti.
Function.caller
arguments.callee
sumber
arguments.callee
dilarang dalam mode ketat. Itu membuatku sedih juga, tapi lebih baik tidak menggunakannya lagi.arguments.callee.caller
sudah usang dalam mode ketat ES5: "Fitur lain yang tidak digunakan lagi adalah arguments.callee.caller, atau lebih khusus Function.caller." ( Sumber )Lebih baik menggunakan fungsi bernama daripada arguments.callee:
lebih baik dari
Fungsi bernama akan memiliki akses ke pemanggil melalui properti pemanggil :
mana yang lebih baik dari
Penghentian ini disebabkan oleh prinsip-prinsip desain ECMAScript saat ini .
sumber
Hanya perpanjangan. Nilai "ini" berubah selama rekursi. Dalam contoh berikut (dimodifikasi), faktorial mendapatkan objek {foo: true}.
faktorial disebut pertama kali mendapatkan objek, tetapi ini tidak benar untuk panggilan rekursif.
sumber
this
perlu dipertahankan, tulisfactorial.call(this, n-1)
saya sebenarnya telah menemukan dalam menulis kode rekursif, yang biasanya tidak adathis
, atauthis
merujuk ke beberapa node di pohon dan sebenarnya itu baik bahwa itu berubah.