SOFTELメモ Developer's blog

会社概要 ブログ 調査依頼 採用情報 ...
てるてる動画

【Javascript】DOM0とDOM1を混ぜると危険?

問題

こんなことがあってびっくりしました。

1、フォーム中のあるinput要素をnameで参照する(DOM0な操作) → 参照できる
2、フォーム中のあるinput要素をremoveChild()した(DOM1な操作)
3、フォーム中のあるinput要素をnameで参照する(DOM0な操作) → まだ参照できる

動作サンプル

↓あるフォームの
↓あるinput要素

↓ボタンクリック: document.forms[‘f20120607’][‘i20120607’].parentNode.removeChild(document.forms[‘f20120607’][‘i20120607’]);

↓ボタンクリック: alert(document.forms[‘f20120607’][‘i20120607’].value);

答え

DOM Level 1 な操作の実装は、統一されてると思うのですが、
(例 document.getElementById(), x.removeChild(y), etc.)

この、いわゆるDOM Level 0 的な操作は、
(例 document.forms[“hoge”].elements[“fuga”])
ブラウザ間で実装がまちまちで、HTML5に伴ってようやく仕様らしいものがまとまってきたと思います。

手順3で消えたはずの要素を参照できるのはおそらくIE以外です。

IE以外は以下のHTML5の仕様に従っているようです。

form[name]

Once an element has been referenced using a particular name, that name will continue being available as a way to reference that element in this method, even if the element’s actual ID or name changes, for as long as the element remains in the Document.

http://www.w3.org/TR/html5/the-form-element.html#the-form-element

フォームの要素に名前でアクセスするとき(例:document.forms[“hoge”][“fuga”] )、その名前で一度アクセスすると、その名前はその要素を参照するために利用し続けることができる。たとえその要素の名前を変更したとしても。

「Documentに残っている限り(for as long as the element remains in the Document.)」というのがどこに定義されているか気になるのですが、removeChildしてもDOMツリーから取り除かれるだけで存在はし続けていることをDocumentに残っているというのならわかります。

また removeChildではなくて、フォームのコントロール(input要素など)のnameを変更するようなスクリプトを実行しても、一度参照したことのある要素は、変わらず以前の名前で参照できるという現象が発生します。

関連するメモ

コメント(1)

優鬼 2022年7月23日 16:38

細かいことはわからないですが、致命的なのは
仕様書にしつこいくらい「DOMは生きている」(オブジェクトは常に最新の状態)とあるので、削除した要素が参照できたらまずいだろうと思います。
モダンなブラウザでサンプルは軒並みエラーになります。