これまで色々と罠にハメられたことのメモ。
Windows版のIE9以降では動くけどIE8では動かないコード。
これまで遭遇した中でも、あんまり再現条件が限定的だったりするものや経緯が複雑だったものは省いています。
(2015/08/26 追記) いくつかの現象は IE8 が ECMAScript3 をベースに、IE9 以上が ECMAScript5 をベースに動作することが原因で発生する現象です。 それらについても追記しました。
グローバル変数を delete
演算子で削除しようとするとエラー
何でなのかわかりません。調べる気も起きませんでした……
window.hoge = 'abc';
// エラー
delete window.hoge; // このオブジェクトではサポートされていない操作です
// 代わりに↓で代用する
window.hoge = void 0; // void 0 は undefined のこと
ECMAScript3 の delete
演算子および Global
オブジェクトについてこのような仕様の言及は無さそうです。
IE8 の Global オブジェクト(=window)には [[Delete]]
メソッドが定義されていないということでしょうか。
DOMエレメントの存在しないプロパティを delete
演算子で削除しようとするとエラー
削除できるうちは大丈夫らしい。
var elem = document.getElementById('fooBar');
elem.foo = 'bar';
delete elem.foo; // true
delete elem.foo; // オブジェクトでサポートされていないプロパティまたはメソッドです。
delete
演算子の仕様的に説明がつかないような……
String
オブジェクトに添え字アクセスすると undefined
やる方が悪い。が、IE9以降では動いてしまうのだ。
特に String.prototype
にメソッドを拡張するときに this
が String
オブジェクトになってしまうので注意。
そもそも charAt
メソッドを使用しましょう。
文字への配列のようなアクセス方法(上記のふたつめの方法)は、 ECMAScript 3 仕様には含まれていません。これらは JavaScript と ECMAScript 5 の機能です。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String
var str = 'abc';
var strObj = new String(str);
// Stringオブジェクト+添え字を組み合わせると文字が取得できない
console.log(strObj[1]); // undefined
// charAt を使えば大丈夫
console.log(strObj.charAt(1)); // 'b'
// string型のプリミティブなら大丈夫
console.log(str[1]); // 'b'
// string型で扱いつつcharAtを使うのが最も無難
console.log(str.charAt(1)); // 'b'
// こんな風にメソッドを追加する場合、this が String オブジェクトにラップされているので注意が必要
String.prototype.lastChar = function() {
return this[this.length - 1]; // IE8 だけ常に undefined が返る
};
添え字によるアクセスが出来ないこと自体は ECMAScript3 の仕様なので全部が全部 IE8 が悪いわけではないですが、以下の点で嫌らしいです。
-
string
型の値(String
オブジェクトでないプリミティブ値)では添え字アクセスが可能 - IE9以降だと動いてしまう(ECMAScript5 で仕様が見直された影響)
誰が悪いとかいう話ではないですが、気をつけた方がいいかと思います(特にインデックスアクセス可能な別言語に慣れている方はやらかしやすい模様です)。
parseInt
に '08'
, '09'
を渡すと 0
にされる
8進数で解釈されるためです。'08'
, '09'
は8進数として不正なため 0
にされます。
そもそも parseInt
を使う意図がなければ私は Number
関数派です。
console.log(parseInt('07')); // 7
console.log(parseInt('08')); // 0
console.log(Number('07')); // 7
console.log(Number('08')); // 8
これは ECMAScript3 の仕様…と言いたいところですが、15.1.2.2 parseInt (string , radix) には以下の記載があるので残念だとは思います。
radix
が0
またはundefined
であり、string
の数が数字0
で始まりx
もX
も続かないとき、実装は、自由な判断で、数を 8 進数とも 10 進数とも解釈してよい。実装はこの場合、 10 進数として数を解釈することが推奨される。
innerHTML に改行コードを含む文字列を代入したあと取り出すと改行コードが消える
以下のコードは IE8 と IE9 以降で動きが違う。
var foo = document.getElementById('foo');
foo.innerHTML = 'hoge \r\n fuga';
console.log( foo.innerHTML ); // IE8では改行コードが消える
それに伴い、例えば jQuery で以下のコードの結果も変わる。
var text = 'hoge \r\n fuga';
console.log( $('#foo').text(text).html() ); // IE8 では \r\n が消える
…こんな仕様の違いに左右されるコードを書かないでよって気もしますが、某ライブラリがこういうことをしていて現象に遭遇したのと、過去にも同じ話に遭遇した記憶があるなぁと思ったのでメモ。