16

ECMAScript 5 a quelques jolis ajouts. John Resig has a good overview here. Voici un bon ECMAScript 5 compatibility table.Quels scripts modernizer existent pour les nouvelles fonctions ECMAScript 5?

Beaucoup de ces choses peuvent être "truquées" pour les navigateurs qui ne supportent pas encore ces fonctions. Connaissez-vous des scripts qui peuvent le faire? Je suis particulièrement intéressé par Object.create.

Par exemple, Douglas Crockford's JSON script vérifie si les fonctions JSON existent avant de les créer.

S'il y avait plus comme le JSON, nous pourrions les inclure quand nous avons besoin d'utiliser les nouvelles fonctions.

+0

Voir aussi http://stackoverflow.com/questions/1890464/is-there-a-library-which-implements-new-javascript-ecmascript-5-methods-for-older/2916063#2916063 –

Répondre

40

Crockford recommends ce genre de Object.create shim:

if (typeof Object.create != "function") { 
    Object.create = function (o) { 
    function F(){} 
    F.prototype = o; 
    return new F; 
    }; 
} 

Mais s'il vous plaît ne le faites pas.

Le problème avec cette approche est que ES5 Object.create a une signature de 2 arguments: d'abord - un objet à hériter de, et le second (en option) - un des propriétés représentant l'objet (ou plutôt, descripteurs) pour ajouter à nouveau objet créé.

Object.create(O[, Properties]); // see 15.2.3.5, ECMA-262 5th ed. 

Ce que nous avons est une mise en œuvre incompatible avec 2 comportements différents. Dans les environnements natifs Object.create, la méthode sait gérer le second argument; dans les environnements sans Object.create natif, ce n'est pas le cas.

Quelles sont les implications pratiques?

Eh bien, s'il y a un code (par exemple, un script tiers) qui veut utiliser Object.create, il est assez raisonnable pour ce code pour ce faire:

if (Object.create) { 
    var child = Object.create(parent, properties); 
} 

- essentiellement en supposant que si Object.create existe, il doit se conformer aux spécifications - accepter le deuxième argument et ajouter les propriétés correspondantes à un objet. Mais, avec le shim mentionné ci-dessus, le second argument est simplement ignoré. Il n'y a même pas une indication de quelque chose qui va mauvais différemment. Un échec silencieux, pour ainsi dire - quelque chose qui est plutôt douloureux à détecter et à réparer.

Pouvons-nous faire mieux? Eh bien, il est en fait impossible de créer une cale entièrement conforme Object.create en utilisant uniquement les installations ES3 (standard). La meilleure solution consiste à créer une méthode wrapper personnalisée.

Il y a, cependant, peu d'autres (moins optimales) que vous pouvez essayer:

1) Informe utilisateur sur l'incapacité de travailler avec le deuxième argument

if (!Object.create) { 
    Object.create = function (o) { 
    if (arguments.length > 1) { 
     throw Error('second argument is not supported'); 
    } 
    // ... proceed ... 
    }; 
} 

2) Essayez de gérer deuxième argument :

if (!Object.create) { 
    Object.create = function (parent, properties) { 
    function F(){} 
    F.prototype = parent; 
    var obj = new F; 
    if (properties) { 
     // ... augment obj ... 
    } 
    return obj; 
    }; 
} 

Notez que les « propriétés » est un objet représentant descripteurs de propriété, non seulement les noms de propriété/val ues, et est quelque chose qui est pas très trivial de (certaines choses ne sont même pas possible, comme le contrôle de énumérabilité d'une propriété):

Object.create(parent, { 
    foo: { 
    value: 'bar', 
    writable: true 
    }, 
    baz: { 
    get: function(){ return 'baz getter'; }, 
    set: function(value){ return 'baz setter'; }, 
    enumerable: true 
    } 
}); 

L'autre incohérence dans la cale d'origine est qu'il ne prend pas soin de l'objet parent étant null.

var foo = Object.create(null); 

Cela crée un objet dont [[Prototype]] est null; en d'autres termes, un objet qui n'hérite d'rien, pas même Object.prototype (dont héritent tous les objets natifs d'ECMAScript).

foo.toString; // undefined 
foo.constructor; // undefined 
// etc. 

Ceci est, par ailleurs, utile pour créer des tables de hachage "appropriées" dans ECMAScript.

Il est possible d'émuler ce comportement, mais uniquement en utilisant des extensions non standard, telles que la propriété "magique" __proto__ (donc l'implémentation ne serait pas très portable ou robuste). La solution à ce problème est similaire: soit émuler complètement l'implémentation ES5, soit notifier l'incohérence/l'échec.

+1

My [Bibliothèque Xccorsors JavaScript ] (http://github.com/eligrey/Xccessors) fournit les fonctions 'Object.defineProperty' et' Object.defineProperties' que vous pouvez utiliser pour la solution # 2. –

+10

C'est très bien repéré et votre connaissance de l'ES5 est solide, mais je pense qu'il vaut la peine de souligner que le code de Crockford est antérieur à ES5 depuis longtemps: la première version vers 2006 et la dernière, début 2008. Il est donc un peu hypocrite de suggérer il «recommande» cette solution de caler sur ES5. – neonski

+7

La dernière fois que j'ai vu Doug parler de cette cale était il y a 3 mois - http: //www.slideshare.net/douglascrockford/javascript-the-good-parts-3292746/36 C'est environ 4 mois après ES5 a été officiellement normalisé (en décembre 09) et est définitivement plus tard que 2008. Mais je ne veux pas blâmer qui que ce soit (désolé si il est sorti de cette façon). Nous faisons tous des erreurs. L'idée est de recommander contre ** l'approche ** et d'expliquer pourquoi. – kangax

Questions connexes