Warum werden bestimmte Funktionsaufrufe in JavaScript als "illegale Aufrufe" bezeichnet?

92

Zum Beispiel, wenn ich das mache:

var q = document.querySelectorAll;

q('body');

In Chrome wird der Fehler "Unzulässiger Aufruf" angezeigt. Ich kann mir keinen Grund vorstellen, warum dies notwendig ist. Zum einen ist dies nicht bei allen nativen Codefunktionen der Fall. Tatsächlich kann ich das tun:

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

var x = new o();

Und alles funktioniert gut. Insbesondere habe ich dieses Problem beim Umgang mit Dokumenten und Konsolen entdeckt. Irgendwelche Gedanken?

user1152187
quelle

Antworten:

153

Das liegt daran, dass Sie den "Kontext" der Funktion verloren haben.

Wenn du anrufst:

document.querySelectorAll()

Der Kontext der Funktion ist documentund wird wie thisbei der Implementierung dieser Methode zugänglich sein .

Wenn Sie nur aufrufen, qgibt es keinen Kontext mehr - es ist windowstattdessen das "globale" Objekt.

Die Implementierung von querySelectorAllversucht zu verwenden, thisaber es ist kein DOM-Element mehr, es ist ein WindowObjekt. Die Implementierung versucht, eine Methode eines DOM-Elements aufzurufen, die für ein WindowObjekt nicht vorhanden ist, und der Interpreter ruft nicht überraschend Foul auf.

Verwenden Sie .bindin neueren Versionen von Javascript Folgendes, um dieses Problem zu beheben :

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

Dadurch wird sichergestellt, dass alle nachfolgenden Aufrufe von qden richtigen Kontext haben. Wenn Sie nicht haben .bind, verwenden Sie dies:

function q() {
    return document.querySelectorAll.apply(document, arguments);
}
Alnitak
quelle
3
Oh, guter Anruf. Sie haben Recht, weil ich Folgendes tun kann: q.apply (document, ['body']); und es funktioniert.
Benutzer1152187
Beachten Sie, dass dies für integrierte Funktionen im IE nicht unbedingt erforderlich ist. Beispielsweise verfügt console.log dort nicht über eine Apply-Methode.
Hugomg
@Alnitak: Ja, es funktioniert überall außer im Internet Explorer und deshalb sollten Sie häufig nur normale Argumente übergeben, wie in function q(x){ return document.querySelectorAll(x); }. Eine andere Sache, die ich an IE-Browserobjekten wirklich mag, ist, dass einige von ihnen eine Ausnahme auslösen, nur wenn Sie versuchen, eine Eigenschaft von ihnen zu lesen, sodass Sie Funktionen if( 'funcname' in browserobject)anstelle der üblichen testen müssen if(browserobject.funcname)!
Hugomg
Ausgezeichnete Antwort, ich war wirklich verwirrt von diesem Phänomen, genau der gleichen Situation wie OP.
temporärer_Benutzername
1
Verblüfft. Danke dir.
rb-
1

In meinem Fall ist ein illegaler Aufruf aufgetreten, weil eine nicht deklarierte Variable als Argument übergeben wurde. Stellen Sie sicher, dass Sie die Variable deklarieren, bevor Sie an die Funktion übergeben.

Fawad
quelle
Das Deklarieren einer Variablen ist in diesem speziellen Fall nicht sinnvoll, da ein illegaler Aufruf stattfindet, da die dom-abhängige Methode aus dem Kontext von DOM aufgerufen wird, da die somethingMethode in dem Moment, in dem Sie q = document tun, den Kontext des Dokuments
verliert
1

Sie können wie folgt verwenden:

let qsa = document.querySelectorAll;
qsa.apply(document,['body']);
Liebe zum Codieren
quelle
0

Noch eine prägnante Lösung:

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