Comment s'assurer que les programmes ES3 fonctionneront dans un moteur ES5?

Ainsi, ECMAScript 5 introduit des incompatibilités avec ECMAScript 3.


Exemple :

De nombreux articles ont été écrits indiquant que this === null || this === undefined this === null || this === undefined est possible en mode ES5 stricte :

 "use strict"; (function () { alert(this); // null }).call(null); 

Mais, ce que la norme suggère vraiment, c'est que les moteurs ES5 permettent également cela en mode non strict :

15.3.4.3 … La valeur thisArg est transmise sans modification comme valeur de valeur. Il s'agit d'un changement à partir de l'édition 3, où un NArg est undefined ou null est remplacé par l'objet global et ToObject est appliqué à toutes les autres valeurs et ce résultat est passé comme la valeur de this valeur.

Actuellement, IE9 est le seul navigateur qui implémente actuellement ES5, et il s'avère que cela risque de rompre les scripts actuels . Génial.


Annix E de spécifications ES5 répertorie des dizaines d'autres incompatibilités.

Alors, quelle est la meilleure façon de vous assurer que nos scripts ES3 bien essayés continueront à fonctionner sans problème? Une sorte de test-suite automatisée? Devons-nous le tester manuellement?

Pour mémoire, l'interprétation de l'ES5 15.3.4.3 du demandeur est incorrecte. Tout appel à une fonction non stricte dans ES5 devrait être observable de la même manière que dans ES3. L'objet global est encore transmis à une fonction non stricte appelée nulle ou non définie comme valeur de valeur.

La partie manquante de l'analyse est 10.4.3 "Entering Function Code":

Les étapes suivantes sont effectuées lorsque le contrôle entre dans le contexte d'exécution pour le code de fonction contenu dans un objet de fonction F , un appelant fourni thisArg et un appeler fourni argumentsList :

  1. Si le code de fonction est un code strict, définissez ThisBinding to thisArg .
  2. Sinon, si thisArg est nul ou indéfini , définissez ThisBinding sur l'objet global.

ES3 a précisé que l'appelant était responsable de remplacer l'objet global par une valeur nulle ou non définie. ES5 spécifie que l'appelant a cette responsabilité (si ce n'est pas une fonction de mode stricte). Pour un code non strict, ceci n'est pas une différence observable. Le changement de spécification ne fait qu'une différence lorsque l'appel est une fonction stricte.

La suite de test automatisée est certainement une bonne idée.

Puisque de plus en plus d'implémentations mettent en œuvre ES5 maintenant , l'exécution de la suite de test pour votre script / bibliothèque / application dans les navigateurs les plus récents est un bon moyen d'assurer la compatibilité.

J'ai une table de compatibilité ES5 , listant le niveau de support de certaines des implémentations les plus populaires. Ce n'est pas exhaustif, mais il montre une direction générale: le dernier IE, WebKit, Chrome et Firefox ont tous un très bon support ES5. Pour un test de conformité complet, vous pouvez toujours exécuter la suite de test ES5 officielle (ce que j'ai en ligne pour la commodité ici ).

S'il n'y a pas de suite de test (ce qui devrait exister, car il est très utile pour quelques autres raisons), vous pouvez simplement exécuter script / library / application dans l'une des implémentations plus récentes (conformes ES5) et voir ce qui fonctionne et ce qui échoue.

L' annexe E de consultation est un autre moyen d'aller. Notez que même si la liste semble assez grande, ce n'est pas aussi grave que cela semble. L'un des objectifs de l'ES5 était de rendre la transition de l'ES3 plus ou moins indolore, de déplacer des changements plus radicaux dans le mode opt-in strict .

De nombreux changements de compatibilité à partir de cette liste risquent de passer inaperçus. Prenons par exemple, changement dans 15.1.1, où global undefined , NaN et Infinity sont maintenant en lecture seule. Compte tenu du fait que les applications saines ne réaffectent pas ces propriétés globales, sauf par erreur , cette modification est plus un "attrapeur d'erreur" plutôt que "app-breaker".

Une autre modification légèrement innocente est en 15.10.2.12, où la classe de caractères en blanc ( \s ) associe maintenant le caractère <BOM> ( U+FEFF ). Compte tenu de tous les écarts dans les implémentations actuelles (même en ce qui concerne ES3), cette modification risque de passer inaperçue dans la majorité des applications.

Cependant, il existe également des changements plus dangereux , comme celui de parseInt et comment il ne traite plus les chaînes en commençant par 0 en tant que valeurs octales. parseInt('010') ne devrait plus produire 8 (bien que certaines implémentations aient choisi de violer délibérément ce comportement ). Et toujours, s'appuyer sur parseInt sans deuxième argument "radix" n'a jamais été une bonne pratique. Donc, si votre application spécifie toujours radix, il n'y a rien à craindre.

Alors, consultez l'Annexe E, testez votre script dans des implémentations plus récentes (de préférence, plusieurs) et suivez les meilleures pratiques . C'est un bon moyen d'assurer la compatibilité.