Assunzioni del compilatore
Questa pagina è stata tradotta da PageTurner AI (beta). Non ufficialmente approvata dal progetto. Hai trovato un errore? Segnala problema →
Per impostazione predefinita, Babel cerca di compilare il tuo codice per replicare il più fedelmente possibile il comportamento nativo. Tuttavia, ciò può comportare la generazione di codice più voluminoso o meno performante, solo per supportare casi limite che potrebbero non interessarti.
A partire da Babel 7.13.0, puoi specificare un'opzione assumptions nella configurazione per indicare a Babel quali assunzioni può fare sul tuo codice, ottimizzando così il risultato della compilazione. Nota: questa funzionalità sostituisce le varie opzioni loose dei plugin con opzioni di alto livello applicabili a più plugin (link RFC).
Ad esempio:
{
"targets": ">0.5%",
"assumptions": {
"noDocumentAll": true,
"noClassCalls": true
},
"presets": ["@babel/preset-env"]
}
Questa è una funzionalità avanzata. Presta attenzione quando abiliti le assunzioni, poiché non sono conformi alle specifiche e potrebbero causare comportamenti imprevisti nel tuo codice.
Stai migrando dalle opzioni loose e spec di @babel/preset-env verso assunzioni granulari? Consulta "Migrazione dalle modalità "loose" e "spec" di @babel/preset-env" per la configurazione equivalente basata su assunzioni, pronta per essere copiata e incollata come punto di partenza.
arrayLikeIsIterable
Quando si effettua lo spread o l'iterazione di un oggetto array-like, si assume che implementi un metodo [Symbol.iterator] con lo stesso comportamento di Array.prototype[Symbol.iterator] nativo, iterando così direttamente i suoi elementi per indice.
Questo può essere utile, ad esempio, per iterare collezioni DOM in browser obsoleti.
let images = $("img");
for (const img of images) {
console.log(img);
}
const copy = [...images];
constantReexports
Quando si riesporta un binding da un modulo, si assume che non cambi e sia quindi sicuro esportarlo direttamente, come se si stesse facendo:
import { value as val } from "dep";
export const value = val;
NOTA: Ciò influisce anche sui plugin transform-modules-umd e transform-modules-amd.
export { value } from "dependency";
constantSuper
La superclasse di una classe può essere modificata in qualsiasi momento tramite Object.setPrototypeOf, rendendo impossibile per Babel conoscerla staticamente. Con questa opzione attiva, Babel assume che non venga mai modificata e corrisponda quindi sempre al valore specificato nella clausola extends nella dichiarazione della classe.
class Child extends Base {
method() {
super.method(2);
}
}
enumerableModuleMeta
Durante la compilazione da ESM a CJS, Babel definisce una proprietà __esModule sull'oggetto module.exports. Si assume che non si iteri mai sulle chiavi di module.exports o di require("your-module") usando for..in o Object.keys, rendendo quindi sicuro definire __esModule come enumerabile.
export const number = 2;
ignoreFunctionLength
Le funzioni possiedono una proprietà .length che riflette il numero di parametri fino all'ultimo parametro non predefinito. Con questa opzione attiva, si assume che il codice compilato non dipenda da questa proprietà .length.
function fn(a, b = 2, c, d = 3) {
return a + b + c + d;
}
ignoreToPrimitiveHint
Quando si utilizzano funzionalità linguistiche che potrebbero richiamare il metodo [Symbol.toPrimitive] degli oggetti, si assume che non modifichino il loro comportamento in base al parametro hint.
let str = `a${foo}b`;
iterableIsArray
Quando si utilizza un oggetto iterabile (nella destrutturazione di array, cicli for-of o spread), si assume che sia un array.
const [first, ...rest] = obj;
call(first, ...obj);
let arr = [first, ...obj];
for (const el of obj) {
console.log(el);
}
mutableTemplateObject
Non utilizzare Object.freeze per l'oggetto template creato per i tagged template literal. Ciò significa sostanzialmente usare l'helper taggedTemplateLiteralLoose invece di taggedTemplateLiteral.
let str = tag`a`;
noClassCalls
Durante la trasformazione delle classi, si assume che vengano sempre istanziate con new e mai chiamate come funzioni.
class Test {
constructor() {
this.x = 2;
}
}
noDocumentAll
Quando si utilizzano operatori che verificano la presenza di null o undefined, si assume che non vengano mai usati con il valore speciale document.all.
let score = points ?? 0;
let name = user?.name;
noIncompleteNsImportDetection
Si assume che nessuna proprietà propria di un oggetto di esportazione di un modulo venga osservata prima dell'inizializzazione.
Ad esempio, quando si tenta di accedere a ns.foo, restituirà undefined sia con questa assunzione attiva che disattivata. La
differenza è che Object.prototype.hasOwnProperty.call(ns, "foo") restituirebbe false quando
noIncompleteNsImportDetection: true.
export var foo;
noNewArrows
Si assume che il codice non tenti mai di istanziare funzioni freccia utilizzando new, operazione non consentita secondo le specifiche.
NOTA: Questa assunzione è impostata di default a true. Verrà impostata di default a false a partire da Babel 8.
let getSum = (a, b) => {
return { sum: a + b }
};
noUninitializedPrivateFieldAccess
History
| Version | Changes |
|---|---|
| v7.24.0 | Added noUninitializedPrivateFieldAccess assumption |
Si assume che il codice non tenti mai di accedere ai campi privati delle classi prima che vengano inizializzati. Ad esempio:
class Foo {
x = this.#y; // #y is not initialized yet
#y = 2;
}
class MyClass {
static #id = 123;
method() {
return MyClass.#id;
}
}
objectRestNoSymbols
Quando si utilizzano pattern rest nella destrutturazione di oggetti, si assume che gli oggetti destrutturati non abbiano chiavi di tipo symbol o che non sia un problema se non vengono copiate.
let { name, ...attrs } = obj;
privateFieldsAsProperties
Si assume che una "soft privacy" sia sufficiente per i campi privati, e quindi che possano essere memorizzati come proprietà pubbliche non enumerabili con un nome univoco (invece di utilizzare un WeakMap esterno). Ciò rende più semplice il debug dei campi privati compilati.
class Foo {
#method() {}
#field = 2;
run() {
this.#method();
this.#field++;
}
}
Quando si utilizzano helper Babel inline, le chiavi stringa generate sono univoche per file e non globali. Ciò potrebbe causare conflitti quando si estendono classi da file diversi con campi privati con lo stesso nome.
privateFieldsAsSymbols
History
| Version | Changes |
|---|---|
| v7.21.0 | Added privateFieldsAsSymbols assumption |
Si assume che una "soft privacy" sia sufficiente per i campi privati, e quindi che possano essere memorizzati come proprietà pubbliche con una chiave di tipo symbol (invece di utilizzare un WeakMap esterno). Ciò rende più semplice il debug dei campi privati compilati.
class Foo {
#method() {}
#field = 2;
run() {
this.#method();
this.#field++;
}
}
pureGetters
Si assume che i getter, se presenti, non abbiano effetti collaterali e possano essere accessibili più volte.
let a = obj;
a.b?.();
setClassMethods
Quando si dichiarano classi, si assume che i metodi non oscurino gli accessor o le proprietà non scrivibili sul prototipo della superclasse, e che il programma non dipenda dal fatto che i metodi siano non enumerabili. Pertanto, è sicuro assegnare i metodi invece di utilizzare Object.defineProperty.
class Foo extends Bar {
method() {}
static check() {}
}
setComputedProperties
Quando si utilizzano proprietà calcolate di oggetti, si assume che l'oggetto non contenga proprietà che sovrascrivono setter definiti nello stesso oggetto, e quindi è sicuro assegnarle invece di definirle utilizzando Object.defineProperty.
let obj = {
set name(value) {},
[key]: val
}
setPublicClassFields
Quando si utilizzano campi pubblici di classe, si assume che non oscurino alcun getter nella classe corrente, nelle sue sottoclassi o nella sua superclasse. Pertanto, è sicuro assegnarli invece di utilizzare Object.defineProperty.
class Test {
field = 2;
static staticField = 3;
}
setSpreadProperties
Quando si utilizza lo spread di oggetti, si assume che le proprietà spreadate non attivino i getter sull'oggetto di destinazione e quindi è sicuro assegnarle invece di definirle utilizzando Object.defineProperty.
const result = {
set name(value) {},
...obj,
};
skipForOfIteratorClosing
Quando si utilizza for-of con un iteratore, questo dovrebbe sempre essere chiuso con .return() e con .throw() in caso di errore. Quando questa opzione è attiva, Babel assume che tali metodi non siano definiti o siano vuoti, ed evita di chiamarli.
for (const val of iterable) {
console.log(val);
}
superIsCallableConstructor
Quando si estendono classi, si assume che la superclasse sia chiamabile. Ciò significa che non sarà possibile estendere classi native o built-in, ma solo classi compilate o costruttori ES5 di tipo function.
class Child extends Parent {
constructor() {
super(42);
}
}
Migrazione dalle modalità "loose" e "spec" di @babel/preset-env
L'opzione loose di @babel/preset-env equivale alla seguente configurazione:
{
"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'opzione spec di @babel/preset-env equivale alla seguente configurazione:
{
"presets": ["@babel/preset-env"],
"assumptions": {
"noNewArrows": false,
}
}