document.all
偽の DOM 内の非プリミティブ オブジェクトです。
たとえば、次のコードは何もしません。
if (document.all) {
alert("hello");
}
誰かがこれがなぜなのか説明できますか?
document.all
偽の DOM 内の非プリミティブ オブジェクトです。
たとえば、次のコードは何もしません。
if (document.all) {
alert("hello");
}
誰かがこれがなぜなのか説明できますか?
免責事項: 私は、このスレッドにつながった質問をツイートした人です :)それは、フロント トレンドの講演で尋ねて答える質問でした。あのツイートはステージに上がる5分前に書きました。
私が尋ねていた質問は次のとおりです。
ECMAScript 仕様では、次のように定義ToBoolean()
されています。
ご覧のとおり、すべての非プリミティブ オブジェクト (つまり、ブール値、数値、文字列、undefined
またはではないすべてのオブジェクトnull
) は、仕様に従って真です。ただし、DOM には、これに対する例外が 1 つあります。偽の DOM オブジェクトです。それがどれだか知っていますか?
答えはdocument.all
です。HTML仕様には次のように書かれています:
all
属性は、フィルターがすべての要素に一致HTMLAllCollection
するノードをルートとするものを返す必要があります。Document
すべてに対して返されるオブジェクトには、いくつかの異常な動作があります。
ユーザー エージェントは、JavaScript の演算子が返されたオブジェクトを値
ToBoolean()
に変換するかのように動作する必要があります。all
false
ユーザー エージェントは 、JavaScriptの
==
and演算子の目的のために、返されるオブジェクトが値と等しいかのよう に動作する必要があります。!=
all
undefined
ユーザー エージェントは
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 にすることです。
要するに、これらのコード サンプルの両方を機能させることです。古い Web ページが引き続き機能するように、ブラウザはこれを行う必要があります。
// Internet Explorer
if (document.all) {
useActiveX()
}
// Netscape Navigator
else {
useOldButStillWorkingCode()
}
document.all.output.innerHTML = 'Hello, world!'
最新のブラウザーは、この時代遅れのものを実装していません。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で始まる非常に長いスレッドがあります。