Mengapa panggilan fungsi tertentu disebut "pemanggilan ilegal" di JavaScript?

97

Misalnya, jika saya melakukan ini:

var q = document.querySelectorAll;

q('body');

Saya mendapatkan kesalahan "Permintaan ilegal" di Chrome. Saya tidak dapat memikirkan alasan apa pun mengapa ini perlu. Pertama, tidak demikian halnya dengan semua fungsi kode asli. Sebenarnya saya bisa melakukan ini:

var o = Object; // which is a native code function

var x = new o();

Dan semuanya bekerja dengan baik. Secara khusus saya telah menemukan masalah ini ketika berhadapan dengan dokumen dan konsol. Ada pemikiran?

pengguna1152187
sumber

Jawaban:

158

Itu karena Anda kehilangan "konteks" dari fungsi tersebut.

Saat Anda menelepon:

document.querySelectorAll()

konteks fungsinya adalah document, dan akan dapat diakses thisdengan penerapan metode itu.

Saat Anda menelepon, qtidak ada lagi konteks - ini adalah objek "global" window.

Implementasi querySelectorAllmencoba untuk menggunakan thistetapi itu bukan lagi elemen DOM, ini adalah Windowobjek. Implementasinya mencoba memanggil beberapa metode elemen DOM yang tidak ada pada Windowobjek dan interpreter secara tidak mengejutkan memanggil foul.

Untuk mengatasi ini, gunakan .binddi versi Javascript yang lebih baru:

var q = document.querySelectorAll.bind(document);

yang akan memastikan bahwa semua permintaan berikutnya qmemiliki konteks yang benar. Jika Anda belum punya .bind, gunakan ini:

function q() {
    return document.querySelectorAll.apply(document, arguments);
}
Alnitak
sumber
3
Oh, panggilan yang bagus. Anda benar karena saya bisa melakukan: q.apply (document, ['body']); dan berhasil.
pengguna1152187
Perhatikan bahwa ini tidak perlu berfungsi untuk fungsi bawaan di IE. Misalnya, console.log tidak memiliki metode terapan di sana.
hugomg
@Alnitak: Ya, ini berfungsi di mana saja kecuali untuk IE dan itulah mengapa Anda harus sering menyampaikan argumen secara normal, seperti pada function q(x){ return document.querySelectorAll(x); }. Hal lain yang sangat saya suka tentang objek browser IE adalah bahwa beberapa di antaranya memberikan pengecualian hanya jika Anda mencoba membaca properti dari objek tersebut, jadi Anda perlu menguji fitur if( 'funcname' in browserobject)daripada yang biasa if(browserobject.funcname)!
hugomg
Jawaban yang sangat bagus, saya benar-benar bingung dengan fenomena ini, situasi yang sama persis dengan OP.
temporary_user_name
1
Pikiran meledak. Terima kasih.
rb-
1

Dalam kasus saya, pemanggilan Illegal terjadi karena melewatkan variabel yang tidak dideklarasikan untuk berfungsi sebagai argumen. Pastikan untuk mendeklarasikan variabel sebelum meneruskan ke fungsi.

Fawad
sumber
mendeklarasikan variabel tidak masuk akal untuk kasus khusus ini karena pemanggilan ilegal terjadi karena metode dependen dom dipanggil keluar dari konteks DOM, karena saat Anda melakukan q = document.sesuatu somethingmetode kehilangan konteks dokumen
Anshul Sahni
1

Anda bisa menggunakan seperti ini:

let qsa = document.querySelectorAll;
qsa.apply(document,['body']);
cinta untuk pengkodean
sumber
0

Satu lagi solusi ringkas:

const q=s=>document.querySelectorAll(s);
q('body');
BenVida
sumber