web-dev-qa-db-ja.com

IE8の壊れたObject.defineProperty実装の回避

ECMAScript5のObject.defineProperty機能を使用して、次のコードを検討してください。

var sayHi = function(){ alert('hi'); };
var defineProperty = (typeof Object.defineProperty == 'function');
if (defineProperty) Object.defineProperty(Array.prototype,'sayHi',{value:sayHi});
else Array.prototype.sayHi = sayHi;
var a = [];
a.sayHi();

これはChromeおよびFirefox4(definePropertyが存在する場合)で機能し、Firefox 3.6(definePropertyが存在しない場合)で機能します。ただし、IE8。 definePropertyを部分的にのみサポート 。その結果、Object.definePropertyメソッドを実行しようとしますが、失敗し(ブラウザにエラーは表示されません)、すべての実行を停止します。ページ上の他のJavaScriptコード。

IE8の壊れた実装を検出して回避するためのより良い方法はありますか?

if (defineProperty){
  try{ Object.defineProperty(Array.prototype,'sayHi',{value:sayHi}); }catch(e){};
}
if (!Array.prototype.sayHi) Array.prototype.sayHi = sayHi;

不思議なことに、私はこれを私の ArraySetMath ライブラリで使用して、これをサポートするブラウザで列挙不可能な配列メソッドを定義し、列挙可能なメソッドへのフォールバックを使用しています古いブラウザ。

26
Phrogz

Try/catchを使用した直接機能テストよりも優れた方法はないと思います。これは実際には、IEチーム自体が ES5 APIへの移行 に関するこの最近の投稿で推奨していることです。

テストをObject.defineProperty({}, 'x', {})のようなものに短縮することができます(Array.prototypeを使用する代わりに)が、それはちょっとした問題です。この例では、正確な機能をテストします(したがって、誤検知の可能性が低くなります)。

22
kangax

Object.definePropertyを使用するnpmからの複数のパッケージでBrowserifyを使用しており、これをにドロップしました。

https://github.com/inexorabletash/polyfill/blob/master/es5.js

7
Michael Benin
Array.prototype.sayHi = function(){ alert('hi'); };

try {
  Object.defineProperty(Array.prototype, 'sayHi', {
    value: Array.prototype.sayHi
  });
}
catch(e){};
0
Abdullah Aydın

私は前にこれにつまずいた。 try…catchステートメントを使用するIMHOは、あまりにも徹底的です。
より効率的な方法は、条件付きコンパイルを使用することです。

/*@cc_on@if(@_jscript_version>5.8)if(document.documentMode>8)@*/
Object.defineProperty && Object.defineProperty(Array.prototype,'sayHi',{value:sayHi});
/*@end@*/ 
0
Knu

同じ種類の問題がありました(つまり、IE 8のObject.definePropertyはDOMのみであり、他のブラウザーのように完全な実装ではありません)が、それはポリフィル用でした。

とにかく、私はIEを使用しているかどうかを確認するために「機能」チェックの使用を終了しました。これは完全ではありませんが、実行できるすべてのテストで機能します。

if (Object.defineProperty && !document.all && document.addEventListener) {
    Object.defineProperty(Array.prototype,'sayHi',{value:sayHi});
} else {
    Array.prototype.sayHi = sayHi;
}

IE <= 8にはdocument.addEventListenerがなく、document.allはW3C標準に対するMicrosoft独自の拡張機能です。これらの2つのチェックは、IEがバージョン8以下であるかどうかのチェックと同等です。

0
Dev Ops