JavaScriptで特定の関数呼び出しが「不正な呼び出し」と呼ばれるのはなぜですか?


93

たとえば、これを行うと:

var q = document.querySelectorAll;

q('body');

Chromeで「不正な呼び出し」エラーが発生します。これが必要な理由は思いつかない。1つは、すべてのネイティブコード関数に当てはまるわけではありません。実際、私はこれを行うことができます:

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

var x = new o();

そして、すべてうまくいきます。特に、ドキュメントとコンソールを扱うときにこの問題を発見しました。何かご意見は?




回答:


154

これは、関数の「コンテキスト」を失ったためです。

あなたが呼び出すとき:

document.querySelectorAll()

関数のコンテキストはdocumentでありthis、そのメソッドの実装によってアクセスできます。

呼び出すだけでqコンテキストはなくなり、window代わりに「グローバル」オブジェクトになります。

の実装はquerySelectorAllを使用しようとしましたthisが、もはやDOM要素ではなく、Windowオブジェクトです。実装は、Windowオブジェクトに存在しないDOM要素のメソッドを呼び出そうとし、インタプリタは当然ながらfoulを呼び出します。

これを解決するに.bindは、JavaScriptの新しいバージョンで使用します。

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

これにより、以降のすべての呼び出しがq正しいコンテキストを持つことが保証されます。あなたが持っていない場合は.bind、これを使用してください:

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

3
ああ、いい電話。私ができるのであなたは正しい:q.apply(document、['body']); そしてそれは動作します。
user1152187 2012年

これは、IEの組み込み関数では必要ありません。たとえば、console.logにはapplyメソッドがありません。
hugomg

@Alnitak:はい、IEを除くすべての場所で機能しfunction q(x){ return document.querySelectorAll(x); }ます。そのため、のように、引数を通常どおりに渡す必要があることがよくあります。IEブラウザオブジェクトについて私が本当に気に入っているもう1つの点は、プロパティを読み取ろうとすると例外がスローされる場合があるためif( 'funcname' in browserobject)、通常の代わりにで機能をテストする必要があることif(browserobject.funcname)です。
hugomg

すばらしい答えです。OPとまったく同じ状況であるこの現象に本当に混乱しました。
temporary_user_name

1
吹き飛ばされた心。ありがとうございました。
rb-

1

私の場合、未宣言の変数を引数として関数に渡すことにより、不正な呼び出しが発生しました。関数に渡す前に変数を宣言してください。


瞬間、あなたDO Q = document.somethingので、DOM依存方法は、DOMのコンテキストで呼び出されているとして、不正な呼び出しが起こっているとして変数を宣言すると、この特定の場合には意味をすることはありませんsomething方法は、文書の文脈を失い
Anshulサーニ

1

あなたはこのように使うことができます:

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

0

もう1つの簡潔なソリューション:

const q=s=>document.querySelectorAll(s);
q('body');
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.