javascript - Trabajando alrededor de la implementación Object.defineProperty rota de IE8
internet-explorer-8 ecmascript-5 (5)
Considere el siguiente código, utilizando la función Object.defineProperty
de 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();
Esto funciona para Chrome y Firefox 4 (donde existe defineProperty
), y funciona para Firefox 3.6 (donde no existe defineProperty
). IE8, sin embargo, solo es compatible parcialmente con defineProperty
. Como resultado, intenta ejecutar el método Object.defineProperty
, pero luego falla (sin que se muestre un error en el navegador) y deja de ejecutar el resto del código JavaScript en la página.
¿Hay una mejor manera de detectar y evitar la implementación dañada de IE8 que:
if (defineProperty){
try{ Object.defineProperty(Array.prototype,''sayHi'',{value:sayHi}); }catch(e){};
}
if (!Array.prototype.sayHi) Array.prototype.sayHi = sayHi;
Para curiosos, estoy usando esto en mi biblioteca ArraySetMath para definir métodos de matriz no enumerables en aquellos navegadores que lo admiten, con un respaldo a métodos enumerables para navegadores más antiguos.
Estoy usando Browserify con el paquete pluralizado desde npm que usa Object.defineProperty y lo coloqué.
https://github.com/inexorabletash/polyfill/blob/master/es5.js
Me encontré con esto antes. En mi humilde opinión usando una declaración try ... catch es demasiado drástica.
Algo más eficiente sería usar compilación condicional:
/*@cc_on@if(@_jscript_version>5.8)if(document.documentMode>8)@*/
Object.defineProperty && Object.defineProperty(Array.prototype,''sayHi'',{value:sayHi});
/*@end@*/
No creo que haya una mejor manera que una prueba directa de características con try / catch. En realidad, esto es exactamente lo que el propio equipo de IE recomienda en esta publicación reciente sobre la transición a ES5 API .
Puede acortar la prueba a algo como Object.defineProperty({}, ''x'', {})
(en lugar de usar Array.prototype
), pero eso es una cuestión menor; su ejemplo prueba la funcionalidad exacta (y por lo tanto tiene menos posibilidades de falsos positivos).
Tenía el mismo problema de tipo (es decir, el Object.defineProperty en IE 8 es solo DOM y no una implementación completa como los otros navegadores), pero era para un polyfill ..
Anyhoo, terminé usando una verificación de ''características'' para ver si estaba usando IE, no es perfecto, pero funciona en todas las pruebas que podría hacer:
if (Object.defineProperty && !document.all && document.addEventListener) {
Object.defineProperty(Array.prototype,''sayHi'',{value:sayHi});
} else {
Array.prototype.sayHi = sayHi;
}
como IE <= 8 no tiene document.addEventListener
, y document.all
es una extensión propietaria de Microsoft al estándar W3C. Estas dos verificaciones son equivalentes a verificar si IE es la versión 8 o inferior.
Array.prototype.sayHi = function(){ alert(''hi''); };
try {
Object.defineProperty(Array.prototype, ''sayHi'', {
value: Array.prototype.sayHi
});
}
catch(e){};