2012-05-24 5 views
50

Per esempio, se faccio questo:Perché determinate chiamate di funzione sono denominate "invocazioni illegali" in JavaScript?

var q = document.querySelectorAll; 

q('body'); 

ottengo un errore "Illegal invocazione" in Chrome. Non riesco a pensare a nessuna ragione per cui è necessario. Per uno, non è il caso con tutte le funzioni di codice nativo. In effetti posso farlo:

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

var x = new o(); 

E tutto funziona perfettamente. In particolare, ho scoperto questo problema quando si tratta di documenti e console. qualche idea?

+0

possibile duplicato di [Perché non è possibile impostare un alias su document.getElementById()?] (Http://stackoverflow.com/questions/10723496/why-cant-one-set-an-alias-to- document-getelementbyid) – Quentin

+1

possibile duplicato di [aliasing della funzione JavaScript non sembra funzionare] (http://stackoverflow.com/questions/1007340/javascript-function-aliasing-doesnt-seem-to-work) – HoLyVieR

+0

duplicato esatto di ["Uncaught TypeError: invocazione illegale" in Chrome] (http://stackoverflow.com/questions/9677985/uncaught-typeerror-illegal-invocation-in-chrome) –

risposta

86

È perché hai perso il "contesto" della funzione.

quando si chiama:

document.querySelectorAll() 

contesto della funzione è document, e sarà accessibile come this dalla realizzazione di tale metodo.

Quando si chiama semplicemente q non c'è più un contesto - è invece l'oggetto "globale" window.

L'implementazione di querySelectorAll tenta di utilizzare this ma non è più un elemento DOM, è un oggetto Window. L'implementazione tenta di chiamare un metodo di un elemento DOM che non esiste su un oggetto Window e l'interprete chiama in modo non sicuro fallo.

Per risolvere questo problema, utilizzare .bind nelle nuove versioni di Javascript:

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

, che farà in modo che tutte le chiamate successive q hanno il giusto contesto. Se non hai .bind, utilizzare questo:

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

Oh, buona chiamata. Hai ragione perché posso fare: q.apply (document, ['body']); e funziona – user1152187

+0

Si noti che questo non funziona necessariamente per le funzioni integrate in IE. Ad esempio, console.log non ha un metodo apply lì. – hugomg

+0

@missingno va bene su Chrome - ancora un altro IE "speciale" credo - sospiro ... – Alnitak

-1

Nel mio caso invocazione illegale si è verificato a causa di passaggio variabile non dichiarata a funzionare come argomento. Assicurati di dichiarare la variabile prima di passare alla funzione.

0

Può accadere per molte ragioni, una delle ragioni più comuni è che si chiama qualcosa che è sia variabile che funzione.

<body> 
<input type="button" value="-" onclick="changeTime(this)"> 
<script> 
    var changeTime = document.getElementsByClassName("changeTimes"); 
    function changeTime(t){ 
      console.dir(t); 
     } 
</script> 
</body> 

quindi in questo caso non è chiaro quale "ChangeTime" che chiamiamo, variabile o funzione, quindi "invocazione illegale".

Problemi correlati