Saltar al contenido principal

Suposiciones del compilador

Traducción Beta No Oficial

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

Por defecto, Babel intenta compilar tu código para que coincida con el comportamiento nativo lo más fielmente posible. Sin embargo, esto a veces implica generar más código de salida o un código más lento, solo para soportar algunos casos extremos que no te interesan.

Desde Babel 7.13.0, puedes especificar una opción assumptions en tu configuración para indicarle a Babel qué suposiciones puede hacer sobre tu código, optimizando así mejor el resultado de la compilación. Nota: esto reemplaza las diversas opciones loose en los plugins en favor de opciones de alto nivel aplicables a múltiples plugins (enlace al RFC).

Por ejemplo:

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

Esta es una funcionalidad avanzada. Ten cuidado al habilitar suposiciones, ya que no cumplen con las especificaciones y podrían romper tu código de formas inesperadas.

consejo

¿Estás migrando desde las opciones loose y spec de @babel/preset-env hacia suposiciones granulares? Consulta "Migrando desde los modos "loose" y "spec" de @babel/preset-env" para obtener la configuración equivalente basada en suposiciones, lista para copiar y pegar como punto de partida.

arrayLikeIsIterable

Al expandir o iterar un objeto tipo array, supone que implementa un método [Symbol.iterator] con el mismo comportamiento que el nativo Array.prototype[Symbol.iterator], iterando así directamente sus elementos por índice.

Esto puede ser útil, por ejemplo, para iterar colecciones DOM en navegadores antiguos.

JavaScript
let images = $("img");

for (const img of images) {
console.log(img);
}

const copy = [...images];

constantReexports

Al reexportar un binding desde un módulo, supone que no cambia y por tanto es seguro exportarlo directamente, como si hicieras:

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

export const value = val;

NOTA: Esto también afecta a los plugins transform-modules-umd y transform-modules-amd.

JavaScript
export { value } from "dependency";

constantSuper

La superclase de una clase puede cambiarse en cualquier momento usando Object.setPrototypeOf, imposibilitando que Babel la conozca estáticamente. Al habilitar esta opción, Babel asume que nunca cambia y por tanto siempre será el valor declarado en la cláusula extends.

JavaScript
class Child extends Base {
method() {
super.method(2);
}
}

enumerableModuleMeta

Al compilar ESM a CJS, Babel define una propiedad __esModule en el objeto module.exports. Supone que nunca iteras sobre las claves de module.exports o de require("your-module") usando for..in u Object.keys, por lo que es seguro definir __esModule como enumerable.

JavaScript
export const number = 2;

ignoreFunctionLength

Las funciones tienen una propiedad .length que refleja el número de parámetros hasta el último no predeterminado. Al habilitar esta opción, supone que el código compilado no depende de esta propiedad .length.

JavaScript
function fn(a, b = 2, c, d = 3) {
return a + b + c + d;
}

ignoreToPrimitiveHint

Al usar características del lenguaje que puedan invocar el método [Symbol.toPrimitive] de objetos, supone que no cambian su comportamiento según el parámetro hint.

JavaScript
let str = `a${foo}b`;

iterableIsArray

Al usar un objeto iterable (en destructuración de arrays, bucles for-of o spreads), supone que es un array.

JavaScript
const [first, ...rest] = obj;

call(first, ...obj);
let arr = [first, ...obj];

for (const el of obj) {
console.log(el);
}

mutableTemplateObject

No usa Object.freeze para el objeto plantilla creado en literales de plantilla etiquetados. Esto significa usar el helper taggedTemplateLiteralLoose en lugar de taggedTemplateLiteral.

JavaScript
let str = tag`a`;

noClassCalls

Al transformar clases, supone que siempre se instancian con new y nunca se invocan como funciones.

JavaScript
class Test {
constructor() {
this.x = 2;
}
}

noDocumentAll

Al usar operadores que verifican null o undefined, asume que nunca se utilizan con el valor especial document.all.

JavaScript
let score = points ?? 0;
let name = user?.name;

noIncompleteNsImportDetection

Asume que no se observa ninguna propiedad propia de un objeto de exportación de módulo antes de su inicialización. Por ejemplo, al intentar acceder a ns.foo, devolverá undefined tanto con esta suposición activada como desactivada. La diferencia es que Object.prototype.hasOwnProperty.call(ns, "foo") devolvería false cuando noIncompleteNsImportDetection: true.

JavaScript
export var foo;

noNewArrows

Asume que el código nunca intenta instanciar funciones flecha usando new, lo cual está prohibido según la especificación.

NOTA: Esta suposición tiene como valor predeterminado true. A partir de Babel 8, el valor predeterminado será false.

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

noUninitializedPrivateFieldAccess

History
VersionChanges
v7.24.0Added noUninitializedPrivateFieldAccess assumption

Asume que el código nunca intenta acceder a campos privados en clases antes de que estén inicializados. Por ejemplo:

JavaScript
class Foo {
x = this.#y; // #y is not initialized yet
#y = 2;
}
JavaScript
class MyClass {
static #id = 123;

method() {
return MyClass.#id;
}
}

objectRestNoSymbols

Al usar patrones de rest en desestructuración de objetos, asume que los objetos desestructurados no tienen claves de símbolo o que no es problema si no se copian.

JavaScript
let { name, ...attrs } = obj;

privateFieldsAsProperties

Asume que la "privacidad débil" es suficiente para campos privados, por lo que pueden almacenarse como propiedades públicas no enumerables con un nombre único (en lugar de usar un WeakMap externo). Esto facilita la depuración de campos privados compilados.

JavaScript
class Foo {
#method() {}

#field = 2;

run() {
this.#method();
this.#field++;
}
}
precaución

Al usar helpers de Babel en línea, las claves de cadena generadas son únicas por archivo, no globalmente. Esto podría causar conflictos al extender clases de diferentes archivos con campos privados del mismo nombre.

privateFieldsAsSymbols

History
VersionChanges
v7.21.0Added privateFieldsAsSymbols assumption

Asume que la "privacidad débil" es suficiente para campos privados, por lo que pueden almacenarse como propiedades públicas con una clave de símbolo (en lugar de usar un WeakMap externo). Esto facilita la depuración de campos privados compilados.

class Foo {
#method() {}

#field = 2;

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

pureGetters

Asume que los getters, si existen, no tienen efectos secundarios y pueden accederse múltiples veces.

JavaScript
let a = obj;

a.b?.();

setClassMethods

Al declarar clases, asume que los métodos no ocultan accesores o propiedades no escribibles en el prototipo de la superclase, y que el programa no depende de que los métodos sean no enumerables. Por tanto, es seguro asignar métodos en lugar de usar Object.defineProperty.

JavaScript
class Foo extends Bar {
method() {}

static check() {}
}

setComputedProperties

Al usar propiedades computadas en objetos, asume que el objeto no contiene propiedades que sobrescriban setters definidos en el mismo objeto, por lo que es seguro asignarlas en lugar de definirlas con Object.defineProperty.

JavaScript
let obj = {
set name(value) {},
[key]: val
}

setPublicClassFields

Al usar campos públicos de clase, asume que no ocultan ningún getter en la clase actual, sus subclases o su superclase. Por tanto, es seguro asignarlos en lugar de usar Object.defineProperty.

JavaScript
class Test {
field = 2;

static staticField = 3;
}

setSpreadProperties

Al usar spread de objetos, asume que las propiedades esparcidas no activan getters en el objeto destino, por lo que es seguro asignarlas en lugar de definirlas con Object.defineProperty.

JavaScript
const result = {
set name(value) {},
...obj,
};

skipForOfIteratorClosing

Al usar for-of con un iterador, este siempre debería cerrarse con .return() y con .throw() en caso de error. Cuando esta opción está activada, Babel asume que esos métodos no están definidos o están vacíos, y evita llamarlos.

JavaScript
for (const val of iterable) {
console.log(val);
}

superIsCallableConstructor

Al extender clases, asume que la superclase es invocable. Esto significa que no será posible extender clases nativas o built-ins, solo clases compiladas o constructores ES5 de tipo function.

JavaScript
class Child extends Parent {
constructor() {
super(42);
}
}

Migrando desde los modos "loose" y "spec" de @babel/preset-env

La opción loose de @babel/preset-env es equivalente a la siguiente configuración:

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
}
}

La opción spec de @babel/preset-env es equivalente a la siguiente configuración:

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