1
/
5

ES Modulesでオブジェクトをバラしてエクスポートするには「exportと分割代入の併用」が便利そう

こんな感じでエクスポートできます。

export const {
  foo,
  bar,
  baz,
} = myObject;

単にexportと分割代入を併用できるというだけの話なので、すでに知っている人には何ということもない話かもしれませんが、筆者は今まで思い付かなかったのでこうして記事にしました。

どういうときに役に立つか

ES Modulesにおいて、独立して動作できるオブジェクトはなるべく個別の名前つきエクスポートに分けてエクスポートしたほうが色々な意味で望ましいですが、使おうとしているライブラリ側がそのように設計されていないこともあります。こういうときはこのような処理が役に立つことがあるでしょう。

また、何らかの事情でCommonJS ModulesとES Modulesのブリッジを自分で書かなければいけなくなったときにも役に立つかもしれません。

他のユースケースとして、何らかのファクトリパターンで生成した複数のオブジェクトをまとめてエクスポートするのにも使える可能性があります。

export const {
  reader,
  writer,
} = createPipe();

なお実際の使用例はここで発見しました。

おまけ: 規格上の根拠

exportと分割代入が併用できることを、念のため規格からも確認しておきます。

"export const" は Declaration を使った ExportDeclaration です。ここでVariableStatementの内容に対して追加の構文的な制限はありません。

このようなexport宣言の効果は以下の2段階に分けられます。

  • ローカル変数を定義する処理
  • 定義したローカル変数をエクスポートする処理

この「ローカル変数を定義する処理」はexportに後続する文の内容がほぼそのまま使われますが、これは以下の二段構成になっています。いずれもexportの有無にかかわらず同じ動作をします。

  • スコープの開始時に束縛を生成する処理
    • これは InitializeEnvironment の一部として行われている。VarScopedDeclarationsとLexicallyScopedDeclarationsに対するループがこれに該当。
    • export constの場合、LexicalDeclarationのBoundNamesに対して束縛が生成される。
    • これはexportが無いconstの場合も同じ結果になる。
  • 右辺を評価し、左辺に代入する処理
    • ExportDeclarationのRuntime Semanticsで定義されている。
    • これはexportが無いバージョンと同じ。

一方、「定義したローカル変数をエクスポートする処理」に使われるのが [[LocalExportEntries]] で、これはモジュールのパース時に決定されます。これは ExportEntries から抽出されるもので、 export Declaration に対する ExportEntries はやはり BoundNames に基づいて決定されていることがわかります。

つまり、exportのついたvar/const/letが分割代入やカンマ区切りによって複数の束縛を生成した場合は、その全てが同名でエクスポートされることになります。

Wantedly, Inc.'s job postings

Weekly ranking

Show other rankings
Invitation from Wantedly, Inc.
If this story triggered your interest, have a chat with the team?