古いWebサイトの改修やリニューアル案件で、急な仕様変更や想定外のバグ対応に追われることはよくありますよね。
今回は、そんなレガシーコードの改修中に遭遇した「IE8環境でのJavaScriptエラー(document.allの挙動の違い)」について情報を共有します。
IE8で「document.all」の仕様が変わっている?
古いコードでよく使われている document.all ですが、IE8において少し厄介な仕様変更(バグ?)が存在します。
同じ要素に対して .length で要素数を取得しようとした場合、以下のような挙動を示します。
document.all("test").lengthと記述した場合- IE7, IE9:正常に要素数を認識する
- IE8:
undefinedとなる
なぜIE8だけエラーになるのか
どうやら、IE8において document.all("nameの値") は「複数の要素があっても、最初の1つのエレメントとしてしか認識しない」という動作を起こすようです。
つまり、同じ name 属性を持つチェックボックスが複数あっても、配列(コレクション)として扱われず、1つ目のチェックボックスしか見ていません。
そのため、本来なら配列に対して使えるはずの .length が機能せず undefined となり、例えば document.all("test")[0].checked = true; のようなコードがJavaScriptエラーを引き起こしてしまうのです。
対処法1:括弧の記述を変える(IE向けの応急処置)
IE8でも配列として認識させるための手っ取り早い対処法は、丸括弧 () を角括弧 [] に変更することです。
- NG:
document.all("test").length - OK:
document.all["test"].length
動作確認用のテストコード
以下のHTMLで簡単な実験を行ってみました。
<!DOCTYPE html>
<html>
<head>
<title>IE8 JAVASCRIPT TEST</title>
<script type="text/javascript">
function submitTest(){
if(document.all){
// ここを () にするか [] にするかで挙動が変わる
if(document.all("test").length != null){
window.alert("true");
}
}
}
</script>
</head>
<body>
<input type="checkbox" name="test" />テスト1
<input type="checkbox" name="test" />テスト2
<input type="checkbox" name="test" />テスト3
<input type="button" onclick="submitTest();" value="テスト実行" />
</body>
</html>各ブラウザの実行結果
- IE7の場合:正常にポップアップ(true)が表示される
- IE8の場合:エラーになり動作しない(undefinedになる)
- IE9の場合:正常にポップアップ(true)が表示される
対処法2:標準のDOMメソッドに書き換える(推奨)
そもそも document.all は、はるか昔のInternet Explorer独自の非標準メソッドです。
クロスブラウザ対応(Chrome、Firefox、Edge、Safariなどで正常に動かすこと)が当たり前となっている現在のWeb標準を考えると、これを機に標準的なDOM操作メソッドへ書き換えることを強く推奨します。
- IDで取得する場合:
document.getElementById("ID名") - name属性で取得する場合:
document.getElementsByName("nameの値")
レガシーサイトの保守は予期せぬ落とし穴が多いですが、一つずつ標準的なコードへリファクタリングしていくことが将来のバグ予防に繋がりますね。