2011-01-27 2 views
26

Consultez le code suivant, en utilisant la fonction de ECMAScript5 Object.defineProperty:Contourner cassé la mise en œuvre de Object.defineProperty 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(); 

Cela fonctionne pour 4 Chrome et Firefox (où existe defineProperty), et cela fonctionne pour Firefox 3.6 (où defineProperty n'existe pas). IE8, cependant, only partially supports defineProperty. Par conséquent, il tente d'exécuter la méthode Object.defineProperty, mais échoue ensuite (sans erreur affichée dans le navigateur) et cesse d'exécuter tous les autres codes JavaScript sur la page.

Y at-il une meilleure façon de détecter et d'éviter la mise en œuvre brisée IE8 que:

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

Pour les curieux, je me sers dans ma bibliothèque ArraySetMath pour définir les méthodes de tableau non-dénombrables dans les navigateurs Soutenez ceci, avec un repli vers des méthodes énumérables pour les navigateurs plus anciens.

Répondre

22

Je ne pense pas qu'il existe un meilleur moyen qu'un test de fonctionnalité directe avec try/catch. C'est en fait exactement ce que l'équipe IE elle-même recommande dans ce récent post sur transitioning to ES5 API.

Vous pouvez raccourcir le test à quelque chose comme Object.defineProperty({}, 'x', {}) (au lieu d'utiliser Array.prototype) mais c'est un petit problème; votre exemple teste la fonctionnalité exacte (et a donc moins de chance de faux positifs).

0

Je suis tombé sur ça avant. À mon humble avis en utilisant une déclaration try ... catch est trop drastique.
Quelque chose plus efficace serait d'utiliser la compilation conditionnelle:

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

J'ai eu la même question genre (la Object.defineProperty dans IE 8 étant DOM et non d'une mise en œuvre complète que les autres navigateurs), mais était un polyfill ..

Anyhoo, j'ai fini en utilisant une « fonction » de vérifier pour voir si j'utilisais IE, ne est pas parfait, mais il fonctionne sur tous les tests que je pouvais faire:

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

comme IE < = 8 n'a pas document.addEventListener, et document.all est une extension Microsoft propriétaire de la norme W3C. Ces deux vérifications sont équivalentes à vérifier si IE est la version 8 ou inférieure.

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

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