Работа над 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 и 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, чтобы определить методы, не перечисленные в массиве, в тех браузерах, которые поддерживают этот, с отступлением от перечислимых методов для старых браузеров.
Ответы
Ответ 1
Я не думаю, что есть лучший способ, чем прямой тест функции с try/catch. На самом деле именно эта команда IE рекомендует в этой недавней публикации переход к API ES5.
Вы можете сократить тест до всего лишь Object.defineProperty({}, 'x', {})
(вместо использования Array.prototype
), но это незначительный каламбур; ваш пример проверяет точную функциональность (и поэтому имеет меньше шансов на ложные срабатывания).
Ответ 2
Я использую Browserify с пакетом pluralize от npm, который использует Object.defineProperty, и я опустил это.
https://github.com/inexorabletash/polyfill/blob/master/es5.js
Ответ 3
Я наткнулся на это раньше. ИМХО, использующее инструкцию try... catch слишком сильно.
Более эффективным было бы использование условной компиляции:
/*@[email protected](@_jscript_version>5.8)if(document.documentMode>8)@*/
Object.defineProperty && Object.defineProperty(Array.prototype,'sayHi',{value:sayHi});
/*@[email protected]*/
Ответ 4
У меня была такая же проблема (то есть Object.defineProperty в IE 8, являющейся только 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 или ниже.
Ответ 5
Array.prototype.sayHi = function(){ alert('hi'); };
try {
Object.defineProperty(Array.prototype, 'sayHi', {
value: Array.prototype.sayHi
});
}
catch(e){};