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


364

単純なHTMLElementラッパーのアイデアを検討しているときに、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これらのブラウザのメソッドの代わりとして使用できることを意味しますか?


6
参照してください私たちはJavaScriptで識別子としての要素IDを使用していないのはなぜ?なぜこれを使用すべきではないのか、そして要素のIDをグローバル変数にする仕様はありますか?それがどのように仕様化されているかについて。
Bergi、2014

1
@Bergi、これをしないと述べているコメントは、現在では古く、無効ですらあります。したがって、この機能を使用しない具体的な理由はわかりません。
ESR

@EdmundReedリンクされた質問の回答をもう一度読みたいと思うかもしれません-それはまだ悪い考えです:「暗黙的に宣言されたグローバル変数」はツールのサポートがなく、「コードがもろくなります」。これを「機能」とは呼ばないでください。以下の回答は、互換性の理由で標準の一部となったバグであることを説明しています。
ベルギ2017

1
@Bergiは十分に公正です、あなたは正しいです。私はまだそれは本当にきちんとした機能だと思います、そして人々がそれを知らないので問題があると考えられるだけです。これは私がそれを使用することを想像する方法です:codepen.io/esr360/pen/WEavGE?editors
ESR

@EdmundReedもちろんコンテンツとロジックを適切に分離しなくても問題は少なくなります。また、インラインイベントハンドラーを使用したり、それらを名前空間として悪用するDOM要素にカスタムメソッドをインストールしたりしないことをお勧めします(「スコープ」ではないことに注意してください)。
ベルギ2017

回答:


395

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

IEは、windowオブジェクトのプロパティとして名前付き要素も追加することで状況を悪化させました。これは、現在、documentまたはwindowオブジェクト(またはプロジェクト内の他のライブラリコード)の使用する可能性のあるです。

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

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

OperaはIEをコピーし、次にWebKitが参加しました。名前付き要素をdocumentプロパティに配置する以前window標準化されて なかった方法と、以前はIEのみでそれらを配置する方法の両方 HTML5によって標準化されています。ブラウザの作者が私たちに課した恐ろしい慣習は、彼らを永遠にウェブの一部にしました。したがって、Firefox 4もこれをサポートします。

「名前付き要素」とは何ですか?を含むものid、およびname「識別」の目的で使用されるものを含むもの:フォーム、画像、アンカーおよびその他のいくつか。ただしname、フォーム入力フィールドのコントロール名、<param>またはのメタデータタイプ<meta>。「特定する」nameは、避けるために避けるべきものですid


5
それは明確な答えです、ありがとう。document.getElementByIdを省略するのは私の考えではありませんでした(実際のところ、今日のところ、要素/要素のプロパティを検索するために可能な限りxpathを使用しています)。私は名前付きアイテムのこの(悪い)習慣に偶然出会い、それがどこから来たのか知りたく思いました。あなたは十分十分にそれに答えました。これで、なぜそれがChrome(webkit)にもあるのかがわかります。
KooiInc 2010

18
「使用のname回避」の1つの例外はで<input>nameフォームの送信用のキーと値のペアのキーを形成する上で属性が重要な役割を果たします。
Yahel、2011

7
FYI Firefoxは、Quirksモードに切り替えたときにのみこれを実行します。
クレセントフレッシュ

4
@yahelc:それはまさに私が作っている区別です。「nameフォーム入力フィールドで同様のコントロール名を他に使用することはできません...」
bobince '17 / 08/17

13
なぜ!?この狂気を止めるために私たちにできることはありますか?要素への参照によって関数が再定義され、デバッグに1時間かかりました。:(
Farzher

52

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

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

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

Webkitは最近 、その反対を検討し、windowオブジェクトの名前付きアクセスを互換モードのみに委任しました。彼らはGeckoと同じ推論によってそれに反対することを決定しました。

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

どうして?グローバル変数が悪い理由についてのこの記事では、多くの推論を要約できます。簡単に言うと、余分なグローバル変数がたくさんあると、より多くのバグが発生します。誤ってaの名前を入力しvar、たまたまidDOMノードのSURPRISE を入力したとします。

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

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

エッジケースで名前付きアクセスを使用すると、さらに多くの機能があると思います。

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

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

興味があれば、ブログで詳しく説明しています-https://www.tjvantoll.com/2012/07/19/dom-element-references-as-global-variables/


3
「使用すべきではない」という前提への明らかな警告へのメモ。つまり、「あなたがたまたまコードカウボーイである場合を除いて、これを使用するべきではありません。」コードカウボーイはそれのためだけに行きます。
Jeremy Foster

5
@jeremyfosterは、「コードカウボーイ」が、開発者に適さない悪質な実装を使用および伝播する人物を意味しない限り、強く同意しません。
Patrick Roberts、

2
良いカウボーイの1つのマークは、多くの人が反対していることです。でも今は哲学的なカウボーイみたいな感じです。
ジェレミー・フォスター

より多くの人々が使用してしなければならないdocument.querySelectorAlldocument.querySelectorDOMにアクセスするとき。+1を使用することをお勧めします。セレクターによる要素へのアクセスは、間違いなくより効率的なプロセスです。
Travis J

20

getElementById()これらのケースでは、次のように固執する必要があります。

document.getElementById('example').innerHTML

IEが持つ要素ミックスするのが好きname IDその最高のあなたが取得しようとしているかについて明確にするために、グローバル名前空間の属性を。


3

はい、彼らがやります。


次の例を使用して、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


1
オペラでも。ただし、このページに記載されているこのメカニズムに対する反対意見は非常によく理解されていると思います。
ncmathsadist

1

「提供されたIDを持つHTMLタグは、グローバルにアクセス可能なDOM要素になるか?」

答えはイエスです!

これが本来の動作方法であり、W3CによってIDが最初に導入されたの はそのためです。解析されたスクリプト環境でのHTMLタグのIDは、対応するDOM要素ハンドルになります。

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

ネットスケープナビゲーター4.7の大失敗の後、開発者たちは全員W3Cに潜入しましたが、彼らの仲間はWebに取って代わって、間違った習慣や誤用例を使用していました。特定のDOM要素にアクセスするためにIDハンドルを利用したスクリプトが壊れるように、ID属性と同等の非推奨のName属性[!

document.all.ElementID.property代わりに、次のような広範なコーディングのレッスンと例を記述して公開するため、彼らはそうしました。 ElementID.property、少なくとも非効率的にし、単にそれを壊さなかった場合に備えてブラウザにオーバーヘッドを与えるそうしました。 (現在[1996-97]、非推奨)名前と同じトークン値を提供する標準ID属性に同じトークンを使用するHTMLドメイン。

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

Mosaic Killers [コードネーム「Mozilla」]は、「私たちが下がればインターネットもそうなるはずだ」と思って大いに腹を立てました。

一方、新興のMicrosoftは非常に素朴だったため、非推奨にして削除のマークを付け、Nameプロパティを一意のIDのIDであるかのように処理して、スクリプトの機能を壊さないようにすべきだと考えました。 Netscapeの研修生によってコード化された古いページ。彼らは致命的に間違っていた...

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

そして、これがW3Cが醜くなり、document.getElementByIdそれに付随するロココのくだらないような構文のような愚かさを私たちに与えた唯一の理由です...(...)

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