59

document.all偽の DOM 内の非プリミティブ オブジェクトです。

たとえば、次のコードは何もしません。

if (document.all) {
    alert("hello");
}

誰かがこれがなぜなのか説明できますか?

4

4 に答える 4

110

免責事項: 私は、このスレッドにつながった質問をツイートした人です :)それは、フロント トレンドの講演で尋ねて答える質問でした。あのツイートはステージに上がる5分前に書きました。


私が尋ねていた質問は次のとおりです。

ECMAScript 仕様では、次のように定義ToBoolean()されています。

ToBoolean(条件)、Front-Trends 2012 トークからのスライド

ご覧のとおり、すべての非プリミティブ オブジェクト (つまり、ブール値、数値、文字列、undefinedまたはではないすべてのオブジェクトnull) は、仕様に従って真です。ただし、DOM には、これに対する例外が 1 つあります。偽の DOM オブジェクトです。それがどれだか知っていますか?

答えはdocument.allです。HTML仕様には次のように書かれています:

all属性は、フィルターがすべての要素に一致HTMLAllCollectionするノードをルートとするものを返す必要があります。Document

すべてに対して返されるオブジェクトには、いくつかの異常な動作があります。

ユーザー エージェントは、JavaScript の演算子が返されたオブジェクトを値ToBoolean()に変換するかのように動作する必要があります。allfalse

ユーザー エージェントは 、JavaScriptの==and演算子の目的のために、返されるオブジェクトが値と等しいかのよう に動作する必要があります。!=allundefined

ユーザー エージェントはtypeof、JavaScript の演算子が'undefined'に対して返されたオブジェクトに適用されたときに 文字列を返すように動作する必要がありますall

これらの要件は、執筆時点で最新の JavaScript 仕様 (ECMAScript エディション 5) に故意に違反しています。JavaScript 仕様では、ToBoolean()オペレーターがすべてのオブジェクトを値に変換する必要があり、オブジェクトが特定のオペレーターの目的のためであるtrueかのように動作するための規定はありません。undefinedこの違反は、レガシー コンテンツの 2 つのクラスとの互換性への欲求によって動機付けられています。1 つは、document.allレガシー ユーザー エージェントを検出する方法として の存在を使用し、もう 1 つは、それらのレガシー ユーザー エージェントのみをサポートし、 document.all最初にその存在をテストせずにオブジェクトを使用します。 .

したがって、document.allこの ECMAScript ルールの唯一の公式な例外です。(Operadocument.attachEventなどでも誤りですが、どこにも明記されていません。)

上記のテキストは、これが行われた理由を説明しています。しかし、これは古い Web ページで非常に一般的なコード スニペットの例であり、これをさらに説明します。

if (document.all) {
  // code that uses `document.all`, for ancient browsers
} else if (document.getElementById) {
  // code that uses `document.getElementById`, for “modern” browsers
}

document.all基本的に、古いブラウザを検出するために長い間この方法が使用されていました。ただし、 が最初にテストされるためdocument.all、両方のプロパティを提供する最新のブラウザーでも、document.allコード パスにたどり着きます。document.getElementByIdもちろん、最新のブラウザでは を使用することを好みますが、ほとんどのブラウザはdocument.all(他の下位互換性の理由から) まだ を使用しているため、 が true のelse場合document.allは決してアクセスされません。コードが別の方法で書かれていれば、これは問題になりません。

if (document.getElementById) {
  // code that uses `document.getElementById`, for “modern” browsers
} else if (document.all) {
  // code that uses `document.all`, for ancient browsers
}

しかし悲しいことに、既存のコードの多くはその逆を行っています。

この問題の最も簡単な解決document.all策は、まだそれを模倣しているブラウザーで単に be falsy にすることです。

于 2012-05-01T07:35:32.647 に答える
7

要するに、これらのコード サンプルの両方を機能させることです。古い W​​eb ページが引き続き機能するように、ブラウザはこれを行う必要があります。

サンプル1

// Internet Explorer
if (document.all) {
    useActiveX()
}
// Netscape Navigator
else {
    useOldButStillWorkingCode()
}

サンプル 2

document.all.output.innerHTML = 'Hello, world!'
于 2015-05-20T19:00:21.580 に答える
7

最新のブラウザーは、この時代遅れのものを実装していません。IE によって導入されましたが、他のほとんどは互換性を保つために "shim" を行っています。

document.all 構文をサポートしながらブラウザーの検出を可能にするために (昔は をテストすることで IE と NN を区別することができました)、他のブラウザーは undefined を返すdocument.all「奇妙な」実装を作成しました。typeof document.all

Opera> document.all
// prints the array-like object
Opera> typeof document.all
"undefined"
Opera> Boolean(document.all)
false

FF がサポートを終了する前は、このメッセージに記載されているように奇妙な動作も示していました。Mozilla バグ #412247でさらに内部を見つけることができます。

また、W3C メーリング リスト アーカイブには、 http://lists.w3.org/Archives/Public/public-html/2009Jun/0546.htmlで始まる非常に長いスレッドがあります。

于 2012-04-27T12:24:39.997 に答える