【JavaScript】ぼく「import文の{}って?」

2024/01/25に公開

はじめに

ナイトウ(@engineer_naito)と申します。

最近Vueを勉強し始めました。

で基礎的な部分の理解が進んできたので、
Vueの公式サイト(https://vuejs.org/)にある実装例集(https://vuejs.org/examples/)を見ながら写経しながら勉強を続けております。

で、公式サイトの実装例集を見てたらふと思ったことがありました。

「import文の{}って何?」

実装例集内のGrid with Sort and FilterのApp.vueのうちのこの部分↓

App.vue
<script setup>
import DemoGrid from './Grid.vue'
import { ref } from 'vue'
...
import DemoGrid from './Grid.vue' # <- {} がない
import { ref } from 'vue'         # <- {} がある

ぼく「import文が2つあるけど {} があるのとないのがあるぞ」
ぼく「import文の {} って何だ?」
ぼく「えー?」

TL;DR

  • {} あり
    名前付きimport

  • {} なし
    デフォルトのimport

JavaScriptのimport

調べていく。
まずは、import - JavaScript - MDN Web Docs - Mozillaを開いて、、、
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/import

import defaultExport from "module-name";
import * as name from "module-name";
import { export1 } from "module-name";
import { export1 as alias1 } from "module-name";
import { default as alias } from "module-name";
import { export1, export2 } from "module-name";
import { export1, export2 as alias2, /* … */ } from "module-name";
import { "string name" as alias } from "module-name";
import defaultExport, { export1, /* … */ } from "module-name";
import defaultExport, * as name from "module-name";
import "module-name";

ぼく「おっ」
ぼく「構文がまとめて書いてある」
ぼく「、、、何言ってるかわからないし読み飛ばしていくか」

import 宣言には 4 つの形式があります:

  • 名前付き import: import { export1, export2 } from "module-name";
  • デフォルトの import: import defaultExport from "module-name";
  • 名前空間の import: import * as name from "module-name";
  • 副作用の import: import "module-name";

ぼく「これだこれだ」
ぼく「 {} のあるのが名前付きimportで、{} がないのがデフォルトのimportになるのか」
ぼく「(難しそうだし下の2つは無視しよ、、、)」

名前付きimport

  • 1モジュールから複数の名前
import { foo, bar } from "/modules/my-module.js";
  • 名前の変更
import { reallyReallyLongModuleExportName as shortName } from "/modules/my-module.js";

デフォルトのimport

  • 好きな名前(デフォルトのexportでは名前を明示していない)
import myDefault from "/modules/my-module.js";
  • 名前付きのimportと一緒に
import myDefault, { foo, bar } from "/modules/my-module.js";

調べてみて

ぼく「なーんだ」
ぼく「思ったよりも簡単じゃないか」

というわけで「JavaScriptのimport文の {} の有無」を完全に理解することができました。

次回は『ぼく「structって?」 #ぼくの大発見日記』の記事でお会いしましょう!

それでは!

言い訳

公式ドキュメントを読んだらすぐわかることだったんですが、ぼくが「JavaScriptのimport文の {} の有無」について疑問を抱いた原因が2つありますので言い訳させてください。
※言語や技術を批判する意思は一切ありません。
※ぼくは言語や技術の 優劣の思想を一切持っていません 。(2024.01.25時点)

Pythonのimport

Python(3)にもimportはありますが、 {} は出てきません!
https://docs.python.org/ja/3/reference/simple_stmts.html#simple-statements

import文がややこしいので、公式チュートリアルの「モジュール」を見ます。

fibo.py
# Fibonacci numbers module

def fib(n):    # write Fibonacci series up to n
    a, b = 0, 1
    while a < n:
        print(a, end=' ')
        a, b = b, a+b
    print()

def fib2(n):   # return Fibonacci series up to n
    result = []
    a, b = 0, 1
    while a < n:
        result.append(a)
        a, b = b, a+b
    return result
  • モジュールをimport
>>> import fibo
>>> fibo.fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> fibo.__name__
'fibo'
  • モジュール内の名前をimport
>>> from fibo import fib, fib2
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
  • モジュール内の名前全部をimport
>>> from fibo import *
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
  • ローカルな名前に代入
>>> fib = fibo.fib
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

{} は出てきませんね。
Pythonを仕事でよく書いていて、Pythonのimportに慣れ親しんでしまったためにぼくは {} ありのimportがよくわからなかったのです。(言い訳その1)

Vueの<script setup>

最初に少し書きましたが、ぼくは最近Vueの勉強を始めました。
どういう動機か忘れてしまいました(特段理由もなかったと思います)が、SFC と Composition API の両方を使って勉強を進めています。

経験としてもJavaScriptに関しては人が書いたjQueryのコードをちょこっと修正するくらいで、理解が足りない部分が多いです。
(以前Angular(1系)のプロジェクトに参画していたこともありますが、コピペを繰り返しており全く習熟していません。)
JavaScriptのコードを0から書いたことがありません。

そんなぼくが初めて?見たVueのコードがこれです。

App.vue
<script setup>
import { reactive, ref } from 'vue'

const counter = reactive({ count: 0 })
const message = ref('Hello World!')
</script>

<template>
  <h1>{{ message }}</h1>
  <p>Count is: {{ counter.count }}</p>
</template>

公式チュートリアル「2. 宣言的レンダリング」 より
(scriptタグ内に {} なしのimport文がありますね。)

このコードのscriptタグも少し特殊なようです。
<script setup> という構文で、Vue3.2から正式に使えるようになった記法とのことです。(https://github.com/vuejs/core/compare/v3.1.5...v3.2.0-beta.1 ですかね)

https://ja.vuejs.org/api/sfc-script-setup#script-setup
<script setup> について公式サイトでは「SFC と Composition API の両方を使うならば、 おすすめの構文です。 」と言っています。
前提条件こそありますが、公式がおすすめと言っているのでまずこれを勉強しない手はないでしょう。

そしてこのおすすめの構文 <script setup> のおかげで export default の記述しなくても動かすことができるようです。

【Vue.js 3.2】<script setup> 構文がすごくすごい という記事で、「export default で Vue.js のオブジェクトを export する必要がなくなった」とあります。

同記事では、 <script setup> を使うのと使わないのとでのコードの比較が行われておりました。

setup属性なし
<template>
  <h1>{{ count }}</h1>
  <button @click="increment">Increment</button>
  <button @click="decrement">Decrement</button>
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";

export default defineComponent({
  setup() {
    const count = ref(0);

    const increment = () => {
      count.value++;
    };

    const decrement = () => {
      count.value--;
    };
    return {
      count,
      increment,
      decrement,
    };
  },
});
</script>
setup属性あり
<script setup lang="ts">
import { ref } from "vue";

const count = ref(0);

const increment = () => {
  count.value++;
};

const decrement = () => {
  count.value--;
};
</script>

<template>
  <h1>{{ count }}</h1>
  <button @click="increment">Increment</button>
  <button @click="decrement">Decrement</button>
</template>

何もわからないぼくでも <script setup> のよさが実感できました。
この便利な構文のおかげでぼくは export default を書く必要がなくなりました。
VueがデフォルトのimportをよしなにやってくれたおかげでJS初心者のぼくは混乱することになってしまったのです。(言い訳その2)

最後に

本当はタイトルの「#ぼくの大発見日記」という部分を「#バカの大発見日記」としたかったのですが、誤解を与える可能性がある気がしたので控えました。
エンジニアになってもう3年経つのですがまだまだ全然初心者です。
少しのことで躓くことが多いです。
これからもこれくらいの感じで、些細な疑問を解決していく記事を書いていくつもりです。
(なるべく自分で調べて、なるべく公式ドキュメントを参照して。)

最後まで読んでいただきありがとうございました!

Discussion