Hypothèses du compilateur
Cette page a été traduite par PageTurner AI (bêta). Non approuvée officiellement par le projet. Vous avez trouvé une erreur ? Signaler un problème →
Par défaut, Babel compile votre code pour qu'il corresponde le plus fidèlement possible au comportement natif. Cela peut toutefois entraîner la génération d'un code plus volumineux ou moins performant, uniquement pour gérer des cas limites qui ne vous concernent pas.
Depuis Babel 7.13.0, vous pouvez spécifier une option assumptions dans votre configuration pour indiquer à Babel quelles hypothèses il peut faire sur votre code, afin d'optimiser le résultat de la compilation. Note : cette approche remplace les diverses options loose des plugins par des paramètres de haut niveau applicables à plusieurs plugins (lien RFC).
Par exemple :
{
"targets": ">0.5%",
"assumptions": {
"noDocumentAll": true,
"noClassCalls": true
},
"presets": ["@babel/preset-env"]
}
Il s'agit d'une fonctionnalité avancée. Soyez prudent lors de l'activation des hypothèses, car elles ne respectent pas les spécifications et peuvent causer des dysfonctionnements imprévisibles dans votre code.
Migrez-vous des options loose et spec de @babel/preset-env vers des hypothèses granulaires ? Consultez "Migration depuis les modes "loose" et "spec" de @babel/preset-env" pour obtenir la configuration équivalente basée sur les hypothèses, prête à être copiée-collée comme point de départ.
arrayLikeIsIterable
Lors de l'étalement (spread) ou de l'itération d'un objet de type tableau, supposez qu'il implémente une méthode [Symbol.iterator] identique à Array.prototype[Symbol.iterator] natif, permettant ainsi d'itérer directement sur ses éléments par index.
Cela peut s'avérer utile, par exemple, pour itérer sur des collections DOM dans d'anciens navigateurs.
let images = $("img");
for (const img of images) {
console.log(img);
}
const copy = [...images];
constantReexports
Lors de la réexportation d'une liaison depuis un module, supposez qu'elle reste inchangée et qu'il est donc sûr de l'exporter directement, comme si vous effectuiez :
import { value as val } from "dep";
export const value = val;
NOTE : Cela affecte également les plugins transform-modules-umd et transform-modules-amd.
export { value } from "dependency";
constantSuper
La superclasse d'une classe peut être modifiée à tout moment via Object.setPrototypeOf, empêchant Babel de la déterminer statiquement. Lorsque cette option est activée, Babel suppose qu'elle reste inchangée et correspond toujours à la valeur spécifiée dans la clause extends de la déclaration de classe.
class Child extends Base {
method() {
super.method(2);
}
}
enumerableModuleMeta
Lors de la compilation d'ESM vers CJS, Babel définit une propriété __esModule sur l'objet module.exports. Supposez que vous n'itérez jamais sur les clés de module.exports ou de require("your-module") via for..in ou Object.keys, ce qui rend sûr de définir __esModule comme énumérable.
export const number = 2;
ignoreFunctionLength
Les fonctions possèdent une propriété .length reflétant le nombre de paramètres jusqu'au dernier paramètre non par défaut. Lorsque cette option est activée, supposez que le code compilé n'utilise pas cette propriété .length.
function fn(a, b = 2, c, d = 3) {
return a + b + c + d;
}
ignoreToPrimitiveHint
Lors de l'utilisation de fonctionnalités susceptibles d'appeler la méthode [Symbol.toPrimitive] des objets, supposez que leur comportement ne varie pas selon le paramètre hint.
let str = `a${foo}b`;
iterableIsArray
Lors de l'utilisation d'un objet itérable (dans une déstructuration de tableau, une boucle for-of ou un étalement), supposez qu'il s'agit d'un tableau.
const [first, ...rest] = obj;
call(first, ...obj);
let arr = [first, ...obj];
for (const el of obj) {
console.log(el);
}
mutableTemplateObject
N'utilisez pas Object.freeze pour l'objet modèle créé avec les littéraux de gabarit étiquetés (tagged template literals). Cela revient à utiliser l'helper taggedTemplateLiteralLoose au lieu de taggedTemplateLiteral.
let str = tag`a`;
noClassCalls
Lors de la transformation de classes, supposez qu'elles sont toujours instanciées avec new et jamais appelées comme des fonctions.
class Test {
constructor() {
this.x = 2;
}
}
noDocumentAll
Lorsque vous utilisez des opérateurs vérifiant null ou undefined, supposez qu'ils ne sont jamais utilisés avec la valeur spéciale document.all.
let score = points ?? 0;
let name = user?.name;
noIncompleteNsImportDetection
Supposez qu'aucune propriété propre d'un objet d'export de module n'est observée avant son initialisation.
Par exemple, lors de l'accès à ns.foo, cela retournera undefined que cette hypothèse soit activée ou désactivée. La
différence est que Object.prototype.hasOwnProperty.call(ns, "foo") retournerait false lorsque
noIncompleteNsImportDetection: true.
export var foo;
noNewArrows
Supposez que le code n'essaie jamais d'instancier des fonctions fléchées avec new, ce qui est interdit par la spécification.
REMARQUE : Cette hypothèse vaut par défaut true. Elle passera par défaut à false à partir de Babel 8.
let getSum = (a, b) => {
return { sum: a + b }
};
noUninitializedPrivateFieldAccess
History
| Version | Changes |
|---|---|
| v7.24.0 | Added noUninitializedPrivateFieldAccess assumption |
Supposez que le code ne tente jamais d'accéder aux champs privés des classes avant leur initialisation. Par exemple :
class Foo {
x = this.#y; // #y is not initialized yet
#y = 2;
}
class MyClass {
static #id = 123;
method() {
return MyClass.#id;
}
}
objectRestNoSymbols
Lors de l'utilisation des motifs de reste dans la déstructuration d'objets, supposez que les objets déstructurés n'ont pas de clés symboles ou que ce n'est pas un problème si elles ne sont pas copiées.
let { name, ...attrs } = obj;
privateFieldsAsProperties
Supposons que la « confidentialité douce » soit suffisante pour les champs privés, et qu'ils puissent donc être stockés en tant que propriétés publiques non énumérables avec un nom unique (plutôt que d'utiliser un WeakMap externe). Cela facilite le débogage des champs privés compilés.
class Foo {
#method() {}
#field = 2;
run() {
this.#method();
this.#field++;
}
}
Lors de l'utilisation des helpers Babel en ligne, les clés de chaîne générées sont uniques par fichier et non globales. Cela peut provoquer des conflits lors de l'extension de classes provenant de fichiers différents avec des champs privés portant le même nom.
privateFieldsAsSymbols
Avec les helpers Babel inline, les clés chaîne générées sont uniques par fichier mais pas globalement. Cela pourrait causer des conflits lors de l'extension de classes avec des champs privés de même nom provenant de fichiers différents.
History
| Version | Changes |
|---|---|
| v7.21.0 | Added privateFieldsAsSymbols assumption |
Supposons que la « soft privacy » soit suffisante pour les champs privés, qui peuvent donc être stockés comme propriétés publiques avec une clé symbolique (plutôt que d'utiliser un WeakMap externe). Cela facilite le débogage des champs privés compilés.
class Foo {
#method() {}
#field = 2;
run() {
this.#method();
this.#field++;
}
}
pureGetters
Supposons que les accesseurs (getters), s'ils sont présents, n'aient pas d'effets secondaires et puissent être accédés plusieurs fois.
let a = obj;
a.b?.();
setClassMethods
Lors de la déclaration de classes, supposez que les méthodes n'écrasent pas les accesseurs ou les propriétés non modifiables du prototype de la superclasse, et que le programme ne dépende pas du caractère non-énumérable des méthodes. Ainsi, il est sûr d'assigner directement les méthodes plutôt que d'utiliser Object.defineProperty.
class Foo extends Bar {
method() {}
static check() {}
}
setComputedProperties
Lors de l'utilisation de propriétés d'objet calculées, supposez que l'objet ne contient pas de propriétés qui écrasent un setter défini dans le même objet, et donc qu'il est sûr de les assigner plutôt que de les définir en utilisant Object.defineProperty.
let obj = {
set name(value) {},
[key]: val
}
setPublicClassFields
Lors de l'utilisation de champs de classe publics, supposez qu'ils ne masquent aucun getter dans la classe actuelle, dans ses sous-classes ou dans sa superclasse. Par conséquent, il est sûr de les assigner plutôt que d'utiliser Object.defineProperty.
class Test {
field = 2;
static staticField = 3;
}
setSpreadProperties
Lors de l'utilisation de la décomposition d'objet, considérez que les propriétés décomposées ne déclenchent pas les accesseurs sur l'objet cible, ce qui rend leur assignation sûre plutôt qu'une définition via Object.defineProperty.
const result = {
set name(value) {},
...obj,
};
skipForOfIteratorClosing
Lors de l'utilisation de for-of avec un itérateur, il doit toujours être fermé avec .return() et avec .throw() en cas d'erreur. Lorsque cette option est activée, Babel suppose que ces méthodes ne sont pas définies ou sont vides, et évite de les appeler.
for (const val of iterable) {
console.log(val);
}
superIsCallableConstructor
Lors de l'extension de classes, partez du principe que la super classe est appelable. Cela signifie qu'il ne sera pas possible d'étendre des classes natives ou des built-ins, mais uniquement des classes compilées ou des constructeurs ES5 function.
class Child extends Parent {
constructor() {
super(42);
}
}
Migration depuis les modes "loose" et "spec" de @babel/preset-env
L'option loose de @babel/preset-env équivaut à la configuration suivante :
{
"presets": [
["@babel/preset-env", { "exclude": ["transform-typeof-symbol"] }]
],
"assumptions": {
"arrayLikeIsIterable": true,
"constantReexports": true,
"ignoreFunctionLength": true,
"ignoreToPrimitiveHint": true,
"mutableTemplateObject": true,
"noClassCalls": true,
"noDocumentAll": true,
"objectRestNoSymbols": true,
"privateFieldsAsProperties": true,
"pureGetters": true,
"setClassMethods": true,
"setComputedProperties": true,
"setPublicClassFields": true,
"setSpreadProperties": true,
"skipForOfIteratorClosing": true,
"superIsCallableConstructor": true
}
}
L'option spec de @babel/preset-env équivaut à la configuration suivante :
{
"presets": ["@babel/preset-env"],
"assumptions": {
"noNewArrows": false,
}
}