web-dev-qa-db-fra.com

Pourquoi certains appels de fonction sont-ils appelés "invocations illégales" en JavaScript?

Par exemple, si je fais ceci:

var q = document.querySelectorAll;

q('body');

Je reçois une erreur "Invocation illégale" dans Chrome. Je ne vois aucune raison pour laquelle cela est nécessaire. D'une part, ce n'est pas le cas avec toutes les fonctions de code natif. En fait, je peux le faire:

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

var x = new o();

Et tout fonctionne bien. En particulier, j'ai découvert ce problème lorsqu’il s’agissait de document et de console. Des pensées?

72
user1152187

C'est parce que vous avez perdu le "contexte" de la fonction.

Quand vous appelez:

document.querySelectorAll()

le contexte de la fonction est document et sera accessible en tant que this par la mise en oeuvre de cette méthode.

Lorsque vous appelez simplement q, il n'y a plus de contexte, mais plutôt l'objet "global" window.

L'implémentation de querySelectorAll essaie d'utiliser this mais ce n'est plus un élément DOM, c'est un objet Window. L'implémentation essaie d'appeler une méthode d'un élément DOM qui n'existe pas sur un objet Window et l'interpréteur appelle sans surprise une faute. 

Pour résoudre ce problème, utilisez .bind dans les versions plus récentes de Javascript:

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

ce qui garantira que toutes les invocations ultérieures de q ont le bon contexte. Si vous n'avez pas .bind, utilisez ceci:

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

vous pouvez utiliser comme ceci: 

let qsa = document.querySelectorAll;
qsa.apply(document,['body']);
0
love-for-coding