2010-09-30 3 views
8

Je vois des articles sur un 'nouvel' Object.create qui rend l'énumération configurable. Cependant, il repose sur une méthode Object.defineProperty. Je ne peux pas trouver une implémentation cross browser pour cette méthode. Sommes-nous en train d'écrire pour l'ancien objet Object.create? Je ne peux pas écrire des choses qui ne fonctionneront pas dans IE6/7.Object.defineProperty dans ES5?

+3

Il y a toujours le cadre Chrome! – kzh

Répondre

14

Il y a plusieurs choses que vous ne pouvez pas imiter la méthode de ECMAScript 5 Object.create sur un environnement ECMAScript 3.

Comme vous l'avez vu, l'argument properties vous donnera des problèmes car dans les implémentations basées sur E3, est pour modifier les attributs de propriétés.

La méthode Object.defineProperty que @Raynos mentionnés, travaille sur IE8, mais partiellement, il peut être utilisé seulement en éléments DOM.

également propriétés accesseur vous donnera des problèmes, ils pourraient être avec largement imité pris en charge des méthodes non standard telles que __defineGetter__/__defineSetter__, mais encore une fois, vous ne pouvez pas changer les attributs propriété.

Un autre problème mis à part les descripteurs de propriétés, est que la méthode Object.create peut accepter null en tant qu'argument, pour créer un objet qui n'hérite d'rien.

Ce ne peut pas être émulé avec le Crockford's Object.create shim, parce que lorsque l'opérateur new est utilisé avec une fonction constructeur qui possède une propriété prototype contenant null -ou tout autre objet non forte valeur, l'objet nouvellement créé hérite de Object.prototype de toute façon par défaut.

Dans certaines implémentations -V8, SpiderMonkey, Rhino, etc ...- ils ont une propriété __proto__ setteable qui pourrait être utilisé pour définir un null [[Prototype]], mais encore une fois, c'est non standard, et bien sûr ça ne marchera jamais sur IE.

Je recommande, si vous souhaitez cibler les anciens navigateurs pour ne pas utiliser ces fonctionnalités, car il n'y a aucun moyen de les faire fonctionner correctement sur ces environnements.

Si vous voulez continuer à utiliser Object.create, sans utiliser les propriétés arguments, vous pouvez, mais je vous recommande de détecter les choses qui ne peuvent être imités.

Ce qui suit serait un plus sûr version du Crockford's Object.create shim:

if (typeof Object.create != 'function') { 
    (function() { 
    var F = function() {}; 
    Object.create = function (o) { 
     if (arguments.length > 1) { throw Error('Second argument not supported');} 
     if (o === null) { throw Error('Cannot set a null [[Prototype]]');} 
     if (typeof o != 'object') { throw TypeError('Argument must be an object');} 
     F.prototype = o; 
     return new F; 
    }; 
    })(); 
} 

Quoi qu'il en soit, l'utiliser avec précaution.

2

Pour ce que ça vaut,

Object.defineProperty œuvres dans IE8 et FF4. Cela signifie qu'il vaut la peine d'utiliser sniff et de l'implémenter là où c'est utile vu que vous espérez que la mise à jour de 6/7 à 8/9 aura lieu dans les prochaines années.

Une autre chose à se méfier est que la propriété dontEnum a un bug dans JScript

Vous devrez travailler autour de la façon dont vous utilisez la propriété dontEnum dans IE.

[Modifier]:

Voici la documentation pour Internet explorer et un lien vers le ES5 specification (Page 122, 15.2.3.6)

+0

C'est bon de savoir que c'est dans IE8, j'ai vu un aperçu de ce qui aurait pu être une implémentation. Donc, ma question est toujours là une implémentation publiée de defineProperty? – Drew

+0

Il n'y a pas une telle mise en œuvre pour IE6/7 J'ai peur. – Raynos

+4

@Drew: 'Object.defineProperty' fonctionne * partiellement * IE8, vous ne pouvez l'utiliser que sur * DOM Elements *. J'ai laissé une [réponse] (http://stackoverflow.com/questions/3830800/object-defineproperty-in-es5/3844768#3844768), qui en bref dit: Vous ne pouvez pas. Les attributs de propriété ne peuvent pas être définis sur des implémentations basées sur ECMAScript 3 .... – CMS

4

Si vous voulez une bonne mise en œuvre DefineProperty(), jetez un oeil à https://github.com/kriskowal/es5-shim

Malheureusement, vous ne pouvez pas faire l'énumération configurable dans un environnement ES3. Ce shim vous permettra d'appeler l'API dans les deux environnements, mais les propriétés seront toujours énumérables sous ES3.

+0

C'est vraiment cool, merci – Drew

Questions connexes