Neden bazı işlev çağrıları JavaScript'te "yasa dışı çağrılar" olarak adlandırılıyor?


97

Örneğin, bunu yaparsam:

var q = document.querySelectorAll;

q('body');

Chrome'da "Yasadışı çağrı" hatası alıyorum. Bunun neden gerekli olduğunu düşünemiyorum. Birincisi, tüm yerel kod işlevlerinde durum böyle değildir. Aslında bunu yapabilirim:

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

var x = new o();

Ve her şey gayet iyi çalışıyor. Özellikle belge ve konsolla uğraşırken bu sorunu keşfettim. Düşüncesi olan var mı?




Yanıtlar:


158

Bunun nedeni, işlevin "bağlamını" kaybetmiş olmanızdır.

Aradığın zaman:

document.querySelectorAll()

işlevin bağlamı document, ve thisbu yöntemin uygulanmasıyla erişilebilir olacaktır .

Sadece aradığınızda qartık bir bağlam yoktur - bunun windowyerine "global" nesnedir.

Uygulanması querySelectorAlldenemeden kullanmak thisancak artık bir DOM elementi, öyle bir var Windownesne. Uygulama, bir Windownesnede olmayan bir DOM öğesinin bazı yöntemlerini çağırmaya çalışır ve yorumlayıcı şaşırtıcı olmayan bir şekilde faul çağırır.

Bunu çözmek için .bind, Javascript’in daha yeni sürümlerinde kullanın :

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

bu, sonraki tüm çağrıların qdoğru bağlama sahip olmasını sağlayacaktır . Eğer yoksa .bind, şunu kullan:

function q() {
    return document.querySelectorAll.apply(document, arguments);
}

3
Güzel görüş. Haklısın çünkü şunları yapabilirim: q.apply (document, ['body']); ve çalışıyor.
user1152187

Bunun, IE'deki yerleşik işlevler için çalışmak zorunda olmadığını unutmayın. Örneğin, console.log burada bir uygulama yöntemine sahip değildir.
hugomg

@Alnitak: Evet, IE haricinde her yerde çalışıyor ve bu yüzden de olduğu gibi normal olarak argümanlar iletmelisiniz function q(x){ return document.querySelectorAll(x); }. IE tarayıcı nesneleri hakkında gerçekten sevdiğim bir diğer şey de, bunlardan bazılarının sadece onlardan bir özelliği okumaya çalışırsanız bir istisna atmasıdır, bu nedenle if( 'funcname' in browserobject)her zamanki yerine özellikleri test etmeniz gerekir if(browserobject.funcname)!
hugomg

Mükemmel cevap, bu fenomen beni gerçekten karıştırdı, OP ile aynı durum.
temporary_user_name

1
Zihin karmaşası. Teşekkür ederim.
rb-

1

Benim durumumda, bağımsız değişken olarak işlev görmesi için bildirilmemiş değişkenin geçirilmesi nedeniyle geçersiz çağrı oluştu. İşleve geçmeden önce değişken bildirdiğinizden emin olun.


Değişken bildirmek bu özel durum için bir anlam ifade etmeyecek çünkü doma bağımlı yöntem DOM bağlamı dışında çağrıldığı için geçersiz çağrı gerçekleşiyor, çünkü yaptığınız anda q = belge. somethingyöntem bir şey belgenin içeriğini kaybeder
Anshul Sahni

1

bunun gibi kullanabilirsiniz:

let qsa = document.querySelectorAll;
qsa.apply(document,['body']);

0

Daha kısa bir çözüm:

const q=s=>document.querySelectorAll(s);
q('body');
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.