js適当マンがコンソールでjavascriptの基礎を学ぶ(importとrequire)

javascriptは基本的にブラウザーの上にのっかっているエンジンなんだけど、結構変わった言語である。で、いちいちブラウザで書いてリロードするのも大変なのでコンソールで実行してみよう。

Hello world的な

hello.js

console.log('Hello, World!');

実行

% node hello.js                             
Hello, World!

ってまあこれはあんま意味がないので

モジュール

greeting.js というものをつくってみよう

export const greeting = 'Hello, World!';

なるほど、greetingという「変数」をexportしている

これをimportしてみると

import { greeting } from './greeting.js';
console.log(greeting);

この初歩中の初歩みたいなコードがまず動かない。

% node hello.js                                                         
(node:83588) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
/home/fukuyama/jswork/hello.js:1
import { greeting } from './greeting.js';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at internalCompileFunction (node:internal/vm:73:18)
    at wrapSafe (node:internal/modules/cjs/loader:1178:20)
    at Module._compile (node:internal/modules/cjs/loader:1220:27)
    at Module._extensions..js (node:internal/modules/cjs/loader:1310:10)
    at Module.load (node:internal/modules/cjs/loader:1119:32)
    at Module._load (node:internal/modules/cjs/loader:960:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:23:47

Node.js v18.17.1

メッセージにあるように、ESモジュールを読みこむにはpackage.jsonでそういう指定をするかmjsという拡張子にしろと行っている。これはいきなり面来らう所である。

require

指定に従わずこのような構文にしてみよう

// import { greeting } from './greeting.js';
// console.log(greeting);
const greetingModule = require('./greeting.js');
console.log(greetingModule.greeting);

greeting.jsも書き換える

// export const greeting = 'Hello, World!';
module.exports.greeting = 'Hello, World!';

これは普通に動作する

% node hello.js                                                                           
Hello, World!


たったこれだけの事なんだけど、結構挙動が違うので最初は戸惑うように思う。まず、importの形式とrequireの形式で違う動きを見せたりするのだった。

AIによるまとめ

すなわち、もともとjsファイルはファイルを分割していわゆるモジュール化する手段を持っていなかったので、最初の方は無理無理requireしていたという状態があるそーな。つまりrequireはそれ自体ブラウザーで動作しきらんようで最終的に「バンドラー」で1つのファイルに纏められる事になるという事のようである。

一方package.jsonを手作りするとmoduleシステムも動作する

import { greeting } from './greeting.js';
console.log(greeting);
export const greeting = 'Hello, World!';

に戻して

{
  "type": "module"
}

こういうjsonを作ると

% node hello.js              
Hello, World!

動く。

import/export moduleの構文

というか、そもそもだが

import { greeting } from './greeting.js';
console.log(greeting);

この受け取り方を名前付きインポート(Named Import)と言うそうな。つまり今

export const greeting = 'Hello, World!';

としているが

export const greeting = 'Hello, World!';
export const farewell = 'Goodbye, World!';

という書き方もできる。受け取る場合は、まあ今greeting.jsに書いてるからアレな感じだけど

import { greeting, farewell } from './greeting.js';
console.log(greeting);
console.log(farewell);

このようにして受け取る。この構文は最近のjavascriptでは頻発すると思うから基礎を抑えておくのが重要っぽいぞと。

もちろん結果は

% node hello.js                                        
Hello, World!
Goodbye, World!

となるわけだ。

今回はここまで。このシリーズ、ちょっと続けていくぞい。

この記事が気に入ったらサポートをしてみませんか?