26

考虑以下代码,使用 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仅部分支持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库中使用它来在支持此功能的浏览器中定义不可枚举的数组方法,并回退到旧浏览器的可枚举方法。

4

5 回答 5

22

我认为没有比使用 try/catch 进行直接功能测试更好的方法了。这实际上正是 IE 团队自己在最近这篇关于过渡到 ES5 API的文章中所建议的。

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

于 2011-02-01T20:44:22.233 回答
7

我正在使用 Browserify 和 npm 的包复数,它使用 Object.defineProperty,我把它放进去了。

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

于 2014-03-12T03:26:11.390 回答
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.addEventListener, 并且document.all是 Microsoft 对 W3C 标准的专有扩展。这两项检查相当于检查 IE 是否为 8 或以下版本。

于 2017-07-01T19:11:58.747 回答
0
Array.prototype.sayHi = function(){ alert('hi'); };

try {
  Object.defineProperty(Array.prototype, 'sayHi', {
    value: Array.prototype.sayHi
  });
}
catch(e){};
于 2017-08-18T13:57:00.133 回答
0

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

/*@cc_on@if(@_jscript_version>5.8)if(document.documentMode>8)@*/
Object.defineProperty && Object.defineProperty(Array.prototype,'sayHi',{value:sayHi});
/*@end@*/ 
于 2017-04-04T18:40:22.867 回答