Aller au contenu principal

Hypothèses du compilateur

Traduction Bêta Non Officielle

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 :

babel.config.json
{
"targets": ">0.5%",
"assumptions": {
"noDocumentAll": true,
"noClassCalls": true
},
"presets": ["@babel/preset-env"]
}
attention

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.

astuce

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.

JavaScript
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 :

JavaScript
import { value as val } from "dep";

export const value = val;

NOTE : Cela affecte également les plugins transform-modules-umd et transform-modules-amd.

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
let getSum = (a, b) => {
return { sum: a + b }
};

noUninitializedPrivateFieldAccess

History
VersionChanges
v7.24.0Added noUninitializedPrivateFieldAccess assumption

Supposez que le code ne tente jamais d'accéder aux champs privés des classes avant leur initialisation. Par exemple :

JavaScript
class Foo {
x = this.#y; // #y is not initialized yet
#y = 2;
}
JavaScript
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.

JavaScript
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.

JavaScript
class Foo {
#method() {}

#field = 2;

run() {
this.#method();
this.#field++;
}
}
attention

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

attention

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
VersionChanges
v7.21.0Added 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.

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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 :

JSON
{
"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 :

JSON
{
"presets": ["@babel/preset-env"],
"assumptions": {
"noNewArrows": false,
}
}