413

単純なラッパーのアイデアに取り組んでいるとHTMLElement、InternetExplorerとChromeで次のことに気づきました。

DOMツリーにが含まれている場合、そのIDを変数名またはのプロパティとして使用して取得HTMLElementできます。だから好きのためにid<div>window<div>

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

Internet Explorer 8とChromeでは、次のことができます。

alert(example.innerHTML); // Alerts "some text".

また

alert(window["example"].innerHTML); // Alerts "some text".

つまり、これは、DOMツリーのすべての要素がグローバルオブジェクトのプロパティに変換されることを意味しますか?getElementByIdまた、これらのブラウザのメソッドの代わりにこれを使用できることも意味しますか?

4

5 に答える 5

437

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

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

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

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

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

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

于 2010-08-08T13:03:05.627 に答える
65

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

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

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

Webkitは最近、反対のことを検討し、オブジェクトへの名前付きアクセスwindowをクァークズモードのみに任せました。彼らはGeckoと同じ理由でそれに反対することを決めました。

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

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

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

  • IEは、nameフォーム要素(input、selectなど)で属性の値に誤ってアクセスできるようにします。
  • 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/

于 2012-07-27T15:54:22.450 に答える
21

getElementById()このような場合は、次のように固執する必要があります。

document.getElementById('example').innerHTML

name IEは、グローバル名前空間で要素と 属性を組み合わせるのが好きなIDので、取得しようとしているものについて明示するのが最善です。

于 2010-08-08T12:29:09.930 に答える
9

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

答えはイエスです!

これが機能することを意図した方法であり、そもそもIDがW3Cによって導入された理由 です。解析されたスクリプト環境でのHTMLタグのIDは、対応するDOM要素ハンドルになります。

しかし、Netscape Mozillaは(侵入する)W3Cに準拠することを拒否し、非推奨のName属性を頑固に使用して大混乱を引き起こしました。そのため、W3Cによる一意のIDの導入によってもたらされたスクリプト機能とコーディングの利便性が損なわれました。

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

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

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

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

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

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

そして、これがW3Cが醜くなりdocument.getElementById、それに付随するロココのような厄介な構文のような馬鹿げたものを私たちに与えた唯一の理由です...(...)

于 2019-02-06T03:18:08.987 に答える
4

はい、彼らはやる。


次の例を使用して、Chrome 55、Firefox 50、IE 11、IE Edge 14、およびSafari10でテストしました。

<!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

于 2016-12-23T14:33:09.777 に答える