web-dev-qa-db-ja.com

IDを持つDOMツリー要素はグローバル変数になりますか?

Internet Explorerと Chrome について次のことを見つけました。

DOMツリー内のIDを持つ特定のHTMLElementについて、そのIDを変数名として使用してdivを取得できます。のようなdivの

<div id="example">some text</div>

Internet Explorer 8 およびChromeでできること:

alert(example.innerHTML); //=> 'some text'

または

alert(window['example'].innerHTML); //=> 'some text'

つまり、これはDOMツリーのすべての要素がグローバル名前空間の変数に変換されるということですか?また、これらのブラウザーでgetElementByIdメソッドの代わりとしてこれを使用できるということですか?

337
KooiInc

起こるはずのことは、「名前付き要素」がdocumentオブジェクトの見かけのプロパティとして追加されることです。これは、要素名がdocumentの実際のプロパティと衝突する可能性があるため、非常に悪い考えです。

IEは、windowオブジェクトのプロパティとして名前付き要素も追加することで状況を悪化させました。これは、あなたが使用するdocumentオブジェクトまたはwindowオブジェクト(またはプロジェクト内の他のライブラリコード)のいずれかのメンバーに名前を付けないようにする必要があるという点で、二重に悪いです。

また、これらの要素はグローバル変数のように見えることも意味します。幸いなことに、この場合、コード内の実際のグローバルvarまたはfunction宣言はそれらをシャドウするため、ここで名前を付けることについてあまり心配する必要はありませんが、衝突する名前でグローバル変数に割り当てをしようとすると忘れますvarを宣言すると、IEでエラーが発生し、値を要素自体に割り当てようとします。

一般的に、varを省略したり、名前付き要素をwindowで表示したり、グローバルとして表示したりすることは悪い習慣と考えられています。 document.getElementByIdに固執します。これは、より広くサポートされており、あいまいさはありません。入力が気に入らない場合は、短い名前で簡単なラッパー関数を作成できます。いずれにしても、ブラウザは通常、getElementById呼び出しを最適化してクイックルックアップを使用するため、id-to-elementルックアップキャッシュを使用しても意味がありません。要素がidを変更するか、ドキュメントに追加/削除されるときに問題が発生するだけです。

OperaはIEをコピーし、WebKitが参加しました。そして、名前付き要素をdocumentプロパティに配置する以前は標準化されていなかったプラクティスと、windowにそれらを配置する以前はIEのみのプラクティスは、両方とも beingHTML5による標準化 。ブラウザの作者によって私たちに与えられたすべての恐ろしい実践を文書化し、標準化するアプローチです。永遠にウェブの。そのため、Firefox 4もこれをサポートします。

「名前付き要素」とは何ですか? idを持つもの、および「識別」目的で使用されるnameを持つもの:つまり、フォーム、画像、アンカーなど、フォーム入力フィールドのコントロール名など、name属性の他の無関係なインスタンス<param>のパラメータ名または<meta>のメタデータタイプ。 「識別」namesは、idを優先して避ける必要があるものです。

375
bobince

前の回答で述べたように、この動作は ウィンドウオブジェクトの名前付きアクセス として知られています。一部の要素のname属性の値とすべての要素のid属性の値は、グローバルwindowオブジェクトのプロパティとして利用可能になります。これらは名前付き要素として知られています。 windowはブラウザのグローバルオブジェクトであるため、名前付きの各要素にはグローバル変数としてアクセスできます。

これはもともとInternet Explorerによって追加され、最終的には、この動作に依存するサイトとの互換性のために、他のすべてのブラウザーによって実装されました。興味深いことに、Gecko(Firefoxのレンダリングエンジン)は quirksモード のみでこれを実装することを選択しましたが、他のレンダリングエンジンは標準モードでそれを残しました。

ただし、Firefox 14以降、 Firefoxは名前付きアクセスをサポートするようになりました 標準モードのwindowオブジェクトでも同様です。なぜ彼らはこれを変えたのですか?標準モードのこの機能に依存しているサイトはまだたくさんあります。 Microsoftは マーケティングデモをリリースしました でしたが、Firefoxでデモが機能しなくなりました。

Webkitは最近 反対と見なされます を使用し、windowオブジェクトの名前付きアクセスをQuirksモードのみに委任しました。彼らはGeckoと同じ推論でそれに反対しました。

だから…この挙動は今や標準モードのすべての主要ブラウザの最新バージョンで使用するのに技術的に安全だのように見えるのでクレイジーだ。ただし、名前付きアクセスは多少便利に思えるかもしれませんが、使用しないでください

どうして? グローバル変数が悪い である理由について、この記事で多くの推論を要約できます。簡単に言うと、余分なグローバル変数がたくさんあると、バグが増えます。誤ってvarの名前を入力し、偶然DOMノードのidを入力したとしましょう。

さらに、標準化されているにもかかわらず、ブラウザの名前付きアクセスの実装にはまだかなりの不一致があります。

  • IEは、フォーム要素(入力、選択など)に対してname属性の値を誤ってアクセス可能にします。
  • GeckoとWebkitは、name属性を介して<a>タグを誤ってアクセス可能にしません。
  • Geckoは、同じ名前の複数の名前付き要素を誤って処理します(参照の配列ではなく、単一のノードへの参照を返します)。

また、Edgeのケースで名前付きアクセスを使用してみれば、さらに多くの機能があると確信しています。

他の回答で述べたように、document.getElementByIdを使用して、idによってDOMノードへの参照を取得します。 name属性によってノードへの参照を取得する必要がある場合は、document.querySelectorAllを使用します。

サイトで名前付きアクセスを使用してこの問題を広めないでください。多くのWeb開発者は、このmagicalの動作を追跡しようとして時間を無駄にしています。標準モードで名前付きアクセスをオフにするには、アクションを実行し、レンダリングエンジンを取得する必要があります。短期的には悪いことをしているいくつかのサイトを破壊しますが、長期的にはウェブを前進させるのに役立ちます。

興味がある場合は、ブログでこれについて詳しく説明します- https://www.tjvantoll.com/2012/07/19/dom-element-references-as-global-variables/ =。

46
TJ VanToll

これらの場合には、getElementById()に固執する必要があります。例えば:

document.getElementById('example').innerHTML

IEは、グローバル名前空間でnameandID属性と要素を混在させるのが好きなので、取得しようとしているものを明示することが最善です。

20
Nick Craver

はい、そうです。

Chrome 55、Firefox 50、IE 11、IE Edge 14、およびSafari 10でテスト済み
次の例:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
  <div id="im_not_particularly_happy_with_that">
    Hello World!
  </div>
  <script>
    im_not_particularly_happy_with_that.innerText = 'Hello Internet!';
  </script>
  <!-- Looking at you W3 HTML5 spec group ಠ_ಠ -->
</body>
</html>

http://jsbin.com/mahobinopa/edit?html,output

3
qff

質問は次のように聞こえます。「提供されたIDを持つHTMLタグは、グローバルにアクセス可能なDOM要素になりますか?」

答えはイエスです!

そのため、W3CはIDを最初から導入しました。解析されたスクリプト環境のHTMLタグのIDは、対応するDOM要素ハンドルになります。

ただし、Netscape MozillaはW3Cに(侵入する)準拠を拒否し、廃止されたName属性を使用して大混乱を引き起こし、W3Cの固有IDの導入によってもたらされたスクリプト機能とコーディングの利便性を破りました。

Netscape Navigator 4.7の大失敗の後、開発者は全員W3Cに潜入しましたが、彼らの仲間は間違った慣行と誤用の例でWebに取って代わりました。特定のDOM要素にアクセスするためにIDハンドルを使用したスクリプトが単純に破損するように、既に非推奨のName属性[!一意ではない]をID属性と同等に強制的に使用および再利用します。

そして、少なくとも非効率にしてブラウザにオーバーヘッドを与えるために、document.all.ElementID.propertyの代わりにElementID.propertyのような広範なコーディングレッスンと例を[とにかくブラウザは認識しない]書いて公開するので、彼らはやった(現在[1996-97]、廃止予定の)名前と同じトークン値を提供する標準ID属性に同じトークンを使用して、HTMLドメインで単純に分割しなかった場合。

彼らは簡単に-当時-名前とIDが実質的に同じであるという無知なコード作成アマチュアの圧倒的な軍隊を説得することができました。ただし、ID属性は短く、したがってバイトを節約し、古代のNameプロパティよりもコーダーにとって便利です。もちろんそれは嘘でした。または-HTMLの発行された記事に取って代わり、スクリプトエンジンからアクセスできるようにするには、タグに名前とIDの両方を提供する必要があることを説得します。

Mosaic Killers [コードネーム "Mozilla"]はとても腹を立てており、「私たちがダウンしたらインターネットもそうだ」と考えていました。

一方、Microsoftの台頭はあまりにも素朴で、廃止予定で削除用にマークされたNameプロパティを保持し、それを一意の識別子であるIDとして扱い、スクリプト機能を壊さないようにする必要があると考えました。 Netscapeの研修生がコーディングした古いページ。彼らは致命的な間違いでした...

また、IDが競合する要素の配列コレクションを返すことも、この意図的な人為的な問題の解決策ではありませんでした。実際、それは全体の目的を打ち負かしました。

そして、これがW3Cがくなり、document.getElementByIdやそれに付随するロココのゴッドダムという厄介な構文のような愚かさを与えた唯一の理由です...(...)

2
Bekim Bacaj