Работа с неработающей реализацией Object.defineProperty в IE8 - PullRequest
26 голосов
/ 27 января 2011

Рассмотрим следующий код, используя функцию Object.defineProperty ECMAScript5:

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 , чтобы определять неперечислимые методы массива в тех браузерах, которые поддерживают это, с отступлением от перечислимых методов для старых браузеров.

Ответы [ 5 ]

22 голосов
/ 01 февраля 2011

Я не думаю, что есть лучший способ, чем прямой тест с использованием try / catch.Это именно то, что сама команда IE рекомендует в этом недавнем посте о переходе на ES5 API .

Вы можете сократить тест до чего-то вроде Object.defineProperty({}, 'x', {}) (вместо использования Array.prototype), но это незначительная ошибка;В вашем примере проверяется точная функциональность (и поэтому вероятность ложных срабатываний меньше).

7 голосов
/ 12 марта 2014

Я использую Browserify с пакетом множественного числа из npm, в котором используется Object.defineProperty, и я уронил это.

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

0 голосов
/ 18 августа 2017
Array.prototype.sayHi = function(){ alert('hi'); };

try {
  Object.defineProperty(Array.prototype, 'sayHi', {
    value: Array.prototype.sayHi
  });
}
catch(e){};
0 голосов
/ 01 июля 2017

У меня была такая же проблема (т. Е. Object.defineProperty в IE 8 был только DOM, а не полной реализацией, как другие браузеры), но это было для полифилла

Во всяком случае, я прекратил использовать функцию проверки, чтобы увидеть, использовал ли я IE, он не идеален, но он работает на всех тестах, которые я мог сделать:

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

, поскольку IE <= 8 не имеет <code>document.addEventListener, а document.all является проприетарным расширением Microsoft к стандарту W3C. Эти две проверки эквивалентны проверке, является ли IE версией 8 или ниже.

0 голосов
/ 04 апреля 2017

Я наткнулся на это раньше.ИМХО, использование оператора try… catch слишком радикально.
Что-то более эффективное - использовать условную компиляцию:

/*@cc_on@if(@_jscript_version>5.8)if(document.documentMode>8)@*/
Object.defineProperty && Object.defineProperty(Array.prototype,'sayHi',{value:sayHi});
/*@end@*/ 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...