解决IE8破坏的Object.defineProperty实现问题

时间:2011-01-27 17:26:33

标签: javascript internet-explorer-8 ecmascript-5

使用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和Firefox 4(其中defineProperty存在),适用于Firefox 3.6(其中defineProperty不存在)。但是,IE8 only partially supports 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库中使用它来在那些支持它的浏览器中定义不可枚举的数组方法,并回退到旧浏览器的可枚举方法。

5 个答案:

答案 0 :(得分:22)

我认为没有比使用try / catch进行直接功能测试更好的方法。这实际上正是IE团队在transitioning to ES5 API最近的帖子中推荐的。

您可以将测试缩短为Object.defineProperty({}, 'x', {})(而不是使用Array.prototype),但这是一个小问题;您的示例测试了确切的功能(因此误报的可能性更小)。

答案 1 :(得分:7)

我使用Browserify和npm中的包使用Object.defineProperty进行复数化,然后将其删除。

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

答案 2 :(得分:0)

我之前偶然发现了这件事。恕我直言,使用try ... catch语句过于激烈 更有效的方法是使用条件编译:

{{1}}

答案 3 :(得分:0)

我遇到了同样的问题(即IE 8中的Object.defineProperty只是DOM而不是其他浏览器的完整实现),但是它适用于polyfill ..

Anyhoo,我最后使用“功能”检查来查看我是否使用IE,它并不完美,但它适用于我能做的所有测试:

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

因为IE< = 8没有document.addEventListenerdocument.all是W3C标准的专有Microsoft扩展。这两项检查相当于检查IE是否为版本8或更低版本。

答案 4 :(得分:0)

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

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