Dlaczego niektóre wywołania funkcji są określane w JavaScript jako „nielegalne wywołania”?


96

Na przykład, jeśli to zrobię:

var q = document.querySelectorAll;

q('body');

W przeglądarce Chrome pojawia się błąd „Nielegalne wywołanie”. Nie mogę wymyślić żadnego powodu, dla którego jest to konieczne. Po pierwsze, nie dotyczy to wszystkich funkcji kodu natywnego. W rzeczywistości mogę to zrobić:

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

var x = new o();

I wszystko działa dobrze. W szczególności odkryłem ten problem podczas pracy z dokumentem i konsolą. jakieś pomysły?




Odpowiedzi:


158

To dlatego, że straciłeś „kontekst” funkcji.

Kiedy zadzwonisz:

document.querySelectorAll()

kontekst funkcji jest documenti będzie dostępny tak, jak thisprzy implementacji tej metody.

Kiedy po prostu dzwonisz, qnie ma już kontekstu - windowzamiast tego jest to obiekt „globalny” .

Implementacja querySelectorAllpróbuje użyć, thisale nie jest już elementem DOM, to Windowobiekt. Implementacja próbuje wywołać pewną metodę elementu DOM, który nie istnieje w Windowobiekcie, a interpreter nie jest zaskakująco nazywany faoul.

Aby rozwiązać ten problem, użyj .bindw nowszych wersjach Javascript:

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

co zapewni, że wszystkie kolejne wywołania będą qmiały właściwy kontekst. Jeśli nie masz .bind, użyj tego:

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

3
Och, dobra rozmowa. Masz rację, ponieważ mogę: q.apply (dokument, ['body']); i to działa.
user1152187

Zauważ, że nie jest to konieczne dla funkcji wbudowanych w IE. Na przykład console.log nie ma tam metody stosowania.
hugomg

@Alnitak: Tak, działa wszędzie z wyjątkiem IE i dlatego często powinieneś po prostu normalnie przekazywać argumenty, tak jak w function q(x){ return document.querySelectorAll(x); }. Inną rzeczą, którą naprawdę lubię w obiektach przeglądarki IE, jest to, że niektóre z nich zgłaszają wyjątek tylko wtedy, gdy próbujesz odczytać z nich właściwość, więc musisz przetestować funkcje za pomocą if( 'funcname' in browserobject)zamiast zwykłych if(browserobject.funcname)!
hugomg

Doskonała odpowiedź, byłem naprawdę zdezorientowany tym zjawiskiem, dokładnie taka sama sytuacja jak OP.
temporary_user_name

1
Rozumiem. Dziękuję Ci.
rb-

1

W moim przypadku wystąpiło niedozwolone wywołanie z powodu przekazania niezadeklarowanej zmiennej do funkcji jako argumentu. Upewnij się, że deklarujesz zmienną przed przejściem do funkcji.


deklarowanie zmiennej nie będzie miało sensu w tym konkretnym przypadku, ponieważ dzieje się nielegalne wywołanie, ponieważ metoda zależna od domeny jest wywoływana z kontekstu DOM, ponieważ w momencie wykonania q = document. coś somethingmetoda traci kontekst dokumentu
Anshul Sahni


0

Jeszcze jedno zwięzłe rozwiązanie:

const q=s=>document.querySelectorAll(s);
q('body');
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.