2011-01-27 11 views
26

considere el siguiente código, usando la función de ECMAScript5 Object.defineProperty:Trabajando aplicación Object.defineProperty roto de IE8

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 defineProperty existe), y funciona para Firefox 3.6 (donde defineProperty no existe). IE8, sin embargo, only partially supports defineProperty. Como resultado, intenta ejecutar el método Object.defineProperty, pero luego falla (sin que se muestre ningún 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 aplicación roto de IE8 que:

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

Para los curiosos, estoy usando esto en mi biblioteca ArraySetMath para definir los métodos de matriz no enumerables de los navegadores que apoye esto, con una reserva de métodos enumerables para navegadores más antiguos.

Respuesta

22

No creo que haya una manera mejor que una prueba de función directa con try/catch. Esto es exactamente lo que recomienda el equipo de IE en esta publicación reciente en transitioning to ES5 API.

Puede acortar la prueba a algo así como Object.defineProperty({}, 'x', {}) (en lugar de usar Array.prototype) pero eso es una objeción menor; su ejemplo prueba la funcionalidad exacta (y tiene menos posibilidades de falsos positivos).

0

me encontré con este antes. En mi humilde opinión, utilizar una declaración try ... catch es demasiado drástica.
Algo más eficiente sería utilizar la compilación condicional:

/*@[email protected](@_jscript_version>5.8)if(document.documentMode>8)@*/ 
Object.defineProperty && Object.defineProperty(Array.prototype,'sayHi',{value:sayHi}); 
/*@[email protected]*/ 
0

que tenía el mismo problema especie (es decir, el Object.defineProperty en IE 8 es DOM y no una implementación completa como los otros navegadores), pero era para un polyfill ..

Anyhoo, que terminó usando una 'característica' comprobar para ver si yo estaba usando IE, no es perfecto, pero funciona en todas las pruebas de lo que podí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 de propiedad de Microsoft para el estándar W3C. Estas dos comprobaciones son equivalentes a verificar si IE es la versión 8 o inferior.

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

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