メインコンテンツへスキップ

コンパイラの前提事項

デフォルトでは、Babelはネイティブの動作にできる限り一致するようにコードをコンパイルしようとします。しかし、これは、気にしないエッジケースをサポートするためだけに、より多くの出力コードを生成したり、出力コードが遅くなったりすることを意味する場合があります。

Babel 7.13.0以降では、設定でassumptionsオプションを指定して、コンパイル結果をより最適化するために、Babelがコードに関してどのような前提を置けるかを伝えることができます。注意: これは、複数のプラグインに適用できるトップレベルオプションを優先して、プラグインのさまざまなlooseオプションを置き換えます(RFCリンク)。

例:

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

これは高度な機能です。前提を有効にする場合は注意してください。これらは仕様に準拠しておらず、予期しない方法でコードを破損させる可能性があります。

ヒント

@babel/preset-envlooseおよびspecオプションから、細かい前提事項への移行を検討していますか?@babel/preset-env"loose"および"spec"モードからの移行」で、コピーして貼り付けるだけで開始できる、同等の前提ベースの設定を確認してください。

arrayLikeIsIterable

配列のようなオブジェクトをスプレッドまたは反復処理する場合、ネイティブのArray.prototype[Symbol.iterator]と同じ動作をする[Symbol.iterator]メソッドを実装していると仮定し、したがって、インデックスによって直接要素を反復処理します。

たとえば、これは古いブラウザでDOMコレクションを反復処理するのに役立ちます。

JavaScript
let images = $("img");

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

const copy = [...images];

constantReexports

モジュールからバインディングを再エクスポートする場合、変更されないと仮定して、次のように直接エクスポートしても安全です。

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

export const value = val;

注: これは、transform-modules-umdおよびtransform-modules-amdプラグインにも影響します。

JavaScript
export { value } from "dependency";

constantSuper

クラスのスーパークラスはObject.setPrototypeOfを使用していつでも変更できるため、Babelが静的にそれを知ることは不可能です。このオプションが有効になっている場合、Babelは変更されないと仮定し、したがって、クラス宣言のextends句に配置された値が常に使用されます。

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

enumerableModuleMeta

ESMをCJSにコンパイルするとき、Babelはmodule.exportsオブジェクトに__esModuleプロパティを定義します。for..inまたはObject.keysを使用してmodule.exportsまたはrequire("your-module")のキーを反復処理しないと仮定し、したがって、__esModuleを列挙可能として定義しても安全です。

JavaScript
export const number = 2;

ignoreFunctionLength

関数には、最後の非デフォルトパラメーターまでのパラメーター数を反映する.lengthプロパティがあります。このオプションが有効になっている場合、コンパイルされたコードがこの.lengthプロパティに依存しないと仮定します。

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

ignoreToPrimitiveHint

オブジェクトの[Symbol.toPrimitive]メソッドを呼び出す可能性がある言語機能を使用する場合、hintパラメーターに基づいて動作を変更しないと仮定します。

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

iterableIsArray

反復可能なオブジェクト(配列の分割代入、for-of、またはスプレッド)を使用する場合、それが配列であると仮定します。

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

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

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

mutableTemplateObject

タグ付きテンプレートリテラルのために作成されたテンプレートオブジェクトにObject.freezeを使用しないでください。これは、事実上taggedTemplateLiteralの代わりにtaggedTemplateLiteralLooseヘルパーを使用することを意味します。

JavaScript
let str = tag`a`;

noClassCalls

クラスを変換するとき、常にnewでインスタンス化され、関数として呼び出されることはないと仮定します。

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

noDocumentAll

nullまたはundefinedを確認する演算子を使用する場合、特別な値document.allでは使用されないと仮定します。

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

noIncompleteNsImportDetection

モジュールエクスポートオブジェクトの独自のプロパティは初期化前に観察されないと仮定します。たとえば、ns.fooにアクセスしようとすると、この前提をオンまたはオフにしても、undefinedが返されます。違いは、noIncompleteNsImportDetection: trueの場合、Object.prototype.hasOwnProperty.call(ns, "foo")falseを返すことです。

JavaScript
export var foo;

noNewArrows

コードが仕様に従って許可されていないnewを使用してアロー関数をインスタンス化しようとしないと仮定します。

注: この前提は、デフォルトでtrueです。Babel 8からは、デフォルトでfalseになります。

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

noUninitializedPrivateFieldAccess

履歴
バージョン変更点
v7.24.0noUninitializedPrivateFieldAccessの前提を追加

コードが初期化される前にクラスのプライベートフィールドにアクセスしようとしないと仮定します。例:

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

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

objectRestNoSymbols

オブジェクトの分割代入でrestパターンを使用する場合、分割代入されたオブジェクトにシンボルキーがないか、コピーされない場合に問題がないと仮定します。

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

privateFieldsAsProperties

プライベートフィールドには「ソフトプライバシー」で十分であると仮定し、したがって、外部のWeakMapを使用するのではなく、一意の名前を持つパブリックな非列挙可能なプロパティとして保存できます。これにより、コンパイルされたプライベートフィールドのデバッグが容易になります。

JavaScript
class Foo {
#method() {}

#field = 2;

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

インラインBabelヘルパーを使用する場合、生成された文字列キーはファイルごとに一意であり、グローバルではありません。これにより、同じ名前のプライベートフィールドを持つ異なるフィールドからクラスを拡張する場合に競合が発生する可能性があります。

privateFieldsAsSymbols

履歴
バージョン変更点
v7.21.0privateFieldsAsSymbolsの前提を追加

プライベートフィールドには「ソフトプライバシー」で十分であると仮定し、したがって、(外部のWeakMapを使用するのではなく)シンボルキーを持つパブリックプロパティとして保存できます。これにより、コンパイルされたプライベートフィールドのデバッグが容易になります。

class Foo {
#method() {}

#field = 2;

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

pureGetters

ゲッターが存在する場合、副作用がなく、複数回アクセスできると仮定します。

JavaScript
let a = obj;

a.b?.();

setClassMethods

クラスを宣言する場合、メソッドがスーパークラスプロトタイプのアクセサーまたは書き込み不可のプロパティをシャドウしないこと、およびプログラムが列挙不可能なメソッドに依存しないと仮定します。したがって、Object.definePropertyを使用するのではなく、メソッドを代入しても安全です。

JavaScript
class Foo extends Bar {
method() {}

static check() {}
}

setComputedProperties

計算されたオブジェクトプロパティを使用する場合、オブジェクトに同じオブジェクトで定義されたセッターを上書きするプロパティが含まれていないと仮定し、したがって、Object.definePropertyを使用して定義するのではなく、それらを代入しても安全です。

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

setPublicClassFields

パブリッククラスフィールドを使用する場合、現在のクラス、サブクラス、またはスーパークラスのゲッターをシャドウしないと仮定します。したがって、Object.definePropertyを使用するのではなく、それらを代入しても安全です。

JavaScript
class Test {
field = 2;

static staticField = 3;
}

setSpreadProperties

オブジェクトのスプレッドを使用する場合、スプレッドされたプロパティがターゲットオブジェクトのゲッターをトリガーしないと仮定し、したがって、Object.definePropertyを使用して定義するのではなく、それらを代入しても安全です。

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

skipForOfIteratorClosing

イテレーターでfor-ofを使用する場合、エラーが発生した場合は、常に.return().throw()で閉じる必要があります。このオプションが呼び出されると、Babelはこれらのメソッドが定義されていないか空であると仮定し、それらを呼び出すことを回避します。

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

superIsCallableConstructor

クラスを拡張する際、スーパークラスは呼び出し可能であると想定してください。これは、ネイティブクラスや組み込みクラスを拡張することはできず、コンパイル済みのクラスまたは ES5 の function コンストラクターのみを拡張できることを意味します。

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

@babel/preset-env"loose" および "spec" モードからの移行

@babel/preset-envloose オプションは、以下の構成と同等です。

JSON
{
"presets": [
["@babel/preset-env", { "exclude": ["transform-typeof-symbol"] }]
],
"assumptions": {
"arrayLikeIsIterable": true,
"constantReexports": true,
"ignoreFunctionLength": true,
"ignoreToPrimitiveHint": true,
"mutableTemplateObject": true,
"noClassCalls": true,
"noDocumentAll": true,
"noObjectSuper": true,
"noUndeclaredVariablesCheck": true,
"objectRestNoSymbols": true,
"privateFieldsAsProperties": true,
"pureGetters": true,
"setClassMethods": true,
"setComputedProperties": true,
"setPublicClassFields": true,
"setSpreadProperties": true,
"skipForOfIteratorClosing": true,
"superIsCallableConstructor": true
}
}

@babel/preset-envspec オプションは、以下の構成と同等です。

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