「JavaScriptは2つの言語になったんだね」において、現状のJavaScriptは ESM2015+ と CommonJS という2つの言語に分岐してしまったと述べました。事実はどうあれ、そう考えたらフラストレーションは緩和されるだろう、という話です。
さて、では2つの言語は統合されるのでしょうか? 統合というよりは、CommonJSが無くなってしまい、ESM2015+ の後継だけが生き残ることで単一言語になるでしょう。比較的早いタイミングで。
CommonJSのモジュール方式は、新しい言語仕様ではなくて、旧来のモジュール無しJavaScriptに対して、工夫してモジュール機能を導入したものです。そのメカニズムというのは、あるファイル内で module.exports という変数に代入した値を、別ファイル内で require関数を呼び出すと得られる、というものです。
例えば、以下の hello.cjs ファイル内でセットした文字列 "Hello" を、world-1.cjs ファイルで使うことができます。
// hello.cjs module.exports = "Hello";
// world-1.cjs const hello = require('./hello.cjs'); console.log(hello + ", world\n");
しかし、module.exports は単なる変数だし、require は単なる関数なので、いくらでもお行儀の悪い使い方ができます。
// world-2.cjs const foo = require; function world() { let s = "Bye"; if (Math.random() >= 0.5) { s = foo('./hello.cjs'); } console.log(s + ", world.\n"); } world();
node world-2.cjs
を実行すると、その出力は Hello, world.
だったり、Bye, world.
だったりします。
「変な使い方をしない」というのは罰則のないモラルに過ぎず、強制するスベはありません*1。
過渡期における暫定的な応急措置として致し方ない方法だったわけですが、JavaScriptが発展し続ける言語であるなら、こんな手法が生き残るはずはありません。もちろん、互換性という課題は変化に抗する大きな圧力になりますが、応急措置は捨てたいという要望のほうが強いだろうと思いますね。
*1:「まっとうな使い方」として動的なモジュール・ローディングが必要な場面はありますが、CommonJSは、静的な宣言で済むことも変数と関数で実現しています。