はじめに
グロースエクスパートナーズ株式会社の中村です。
この記事は グロースエクスパートナーズ Advent Calendar 2025 の19日目です。
アドベントカレンダー特別企画として、古くからJavaScriptに携わってきたテクニカルフェロー北條さんとの座談会を、第1回、第2回に続く第3回としてお届けします。今回が最終回になります。
1. モジュールシステムの進化 — グローバル汚染からの解放
グローバル汚染との戦い
👤 司会:
JavaScriptでの開発のやり方は、だいぶ変わりましたよね。
💡 北條:
require.jsとNode.jsが普及し始めた頃、パッケージングと名前空間管理の標準スタイルが確立されたのが大きいですね。それまではScheme由来のノリで、グローバル名前空間に何でもばらまきながら書かざるを得ないようなところがあったんですね。そのため、新しくJavaScriptのモジュールを書くというときには、ファイルの頭と末尾をfunctionで包むというおまじないを必ず書いてから始めるというふうにしていました。グローバル名前空間を汚さないように、新しく書くコードをまず関数の中に詰め込んでおくっていう作業が普通に行われていたんです。エクスポートするものについては、例えばwindow.なんちゃらって名前をつけて、そこにエクスポートするものを入れるというやり方でしたね。
即時関数(IIFE)とグローバル汚染対策
ES Module登場以前、JavaScriptのファイルをすべて<script>タグで読み込む時代は、すべてのコードが同一のグローバルスコープ(window)を共有していました。そのため、varで宣言した変数も、意図せずグローバルに漏れ出てしまいます。
この問題を解決するための定番テクニックが即時関数(IIFE: Immediately Invoked Function Expression)でした:
// 古典的なIIFEパターン
(function() {
// この中の変数はグローバルに漏れない
var privateData = "内部データ";
function privateHelper() {
// ヘルパー関数も外から見えない
}
// 必要なものだけwindowにエクスポート
window.MyModule = {
publicMethod: function() {
return privateData;
}
};
})();
仕組み:
- 関数スコープを作ることで、内部の変数を外部から隠蔽
- 定義と同時に
()で即座に実行するため、グローバルに関数名も残らない -
window.MyModuleのような明示的なエクスポートだけが外部から利用可能に
当時のワークフロー:
- 新しいJSファイルを作る
- 最初に
(function() {と書き、最後に})()で閉じる - コードを実装
- エクスポートしたいAPIだけ
windowに追加
この「おまじない」によって、Scheme由来のレキシカルスコープを活かしつつ、複数ファイルでもグローバル汚染を防ぐことができました。ES Moduleのimport/exportが標準化された現在では、こうした手動の名前空間管理は不要になりましたが、JavaScriptの柔軟性を支えた重要なイディオムでした。
ES Module以前のチーム開発
👤 司会:
最近JavaScriptを始めた人は知らないと思うんですけど、昔はvarで変数宣言すると他ファイルまで影響が飛んでいましたよね。
💡 北條:
varを書かなくても同じことができてしまいます(笑)。変数名を間違えるとグローバル空間によくわからないものがばらまかれるというのがあったりして。
まあでもLISPの伝統通りにやれば問題ないけど、知らない人がやると、大規模なプログラムは書けないですね。書いたら大変なことに多分なっちゃうというような状況です。
当時は、プロジェクトの開始時に名前空間の管理をどういうスタイルでやろうねっていう相談をまずしていました。それでプロジェクト共通の書き方みたいなのを決めてから、コードを書かないと大変なことになっちゃうっていう感じですね、昔のJavaScriptは。例えば、オブジェクト指向的に書くときには、プロトタイプ継承をどういうスタイルで記述するのかっていうのも事前に決めて。それで、それ用のユーティリティを書いてからやるとか。
あと、Prototype.jsとか、jQueryですね。その辺の書き方が何種類か用意されているので、それの中から、じゃあこういうスタイルで、このプロジェクトは書くことにしましょうみたいなのを決めてやれるんですね。
そういう意味では、そのプロジェクトの性質だったり、メンテナンスしていくエンジニアのスキルレベルだったり、プロジェクトの環境に合わせていろんなことができるというのは良いところでしたね。チーム開発は大変だったけど、柔軟性はすごくあるので。まあ、ちゃんとわかっている人が混ざっていれば、そんなにびっくりするようなことにはならないです。
しかし、構文だったり、ブラウザ互換性だったり、そういうのはめちゃくちゃだったので、そっちの方が悲惨でしたね。
ES Moduleが入って、その辺のやり方っていうのは標準化されました。昔はオープンソースのライブラリを持ってくるっていうと、その辺のしきたりがマッチするのかどうかっていうのがすごく悩ましいところだったんですけど、そういうのは標準化されて、いろいろ検討しなくても混ぜて使えるようになったというのは、やっぱり大きなことかなと思います。
ESモジュール以前のグローバル空間事情
-
仕組み:
<script>で読み込んだファイルはすべて同じグローバルスコープを共有し、var(や未宣言変数)はwindow直下にぶら下がる。 -
事故例: 変数名タイポで未宣言のままグローバルに生え、別ファイルの同名変数を上書き/
Prototype.jsがArray.prototypeを拡張し、他ライブラリが想定外メソッドを拾って挙動が変わる/同名ユーティリティを後から読み込んで前定義を潰す、など。 -
当時の対策: ファイル全体を
IIFEで包んで擬似スコープを作る、MYAPP.utils.Fooのような手動名前空間を決めて運用、読み込み順を厳密にルール化する──といった対策をしていた。
ES Moduleとimport/exportの標準化で、こうした衝突と順序依存からようやく解放された。
2. Ajax革命 — XMLHttpRequestがもたらした変化
👤 司会:
XMLHttpRequestさえも使えなかった時代があったというコメントをいただいています。
💡 北條:
最初はなかったですね。JavaScriptというのは、入力フォームのチェックに主に使われていた感じでした。JavaScriptの役割はかなり小さかった。scriptタグの中にちょっとしたのを書いて、という感じでした。
当時はDOMをいじっても画面の描画が更新されない、そんなこともたくさんありましたからね。ブラウザごとに挙動が違ったし。色変えるぐらいはDOMいじりで安心してできるんですけど、位置をずらすとか、表示を消すとかいうと、途端に難易度が上がっちゃうっていうね。
👤 司会:
XMLHttpRequestが一般的になってからはどうでしたか?
💡 北條:
当時、Google MapsやGmailが公開され、XMLHttpRequestによる非同期通信を利用することでブラウザアプリとは思えない挙動を実現したのは革命のようでした。
サーバーサイドから順次必要な情報を引き出しながら処理ができるようになったのは、大きいですね。
👤 司会:
現在では、Reactなどのフレームワークが非同期通信まわりを抽象化して処理してくれるため、開発者が「Ajax」という概念を意識すること自体あまりないように思います。しかし当時は、開発者がXMLHttpRequestを直接扱い、手動でAjax処理を実装していたのですよね?
💡 北條:
そうです。それしかやりようがなかったんです。
ブラウザ毎にまず関数の名前が違うし、パラメータもコールバックも違うので、ラッパーを1枚かませて実装する必要がありました。対応ブラウザどれにしますか?というのは、結構プロジェクトの最初の方で聞いておかないとやばい。今だとなかなか聞かない話ですよね。
3. CoffeeScript — TypeScript以前の救世主
👤 司会:
現在はTypeScriptでの開発が世の中的には主流ですが、TypeScript登場前にはCoffeeScriptというAltJSもありました。
北條さんはCoffeeScriptが好きで、結構書かれていたんですよね。
💡 北條:
当時のJavaScriptは本当にひどい状態で、ブラウザ間の互換性なんて悲惨としか言いようがない状況でした。
CoffeeScriptは、トランスパイル(JavaScriptを別の構文で書き、JavaScriptに変換して使う)という方法で「綺麗に書けるJavaScript」を実現しました。CoffeeScriptの貢献は相当なもので、今のJavaScriptの構文や、TypeScript、Babelなどに繋がる革新的なアイデアでした。
JavaScriptのどうしようもない制約に振り回されないように、毎回変なボイラープレートを書かなくて済む――という点で、CoffeeScriptが登場したときにはもう飛びつきました。「これでやっと綺麗に効率よく書けるようになった」と思ったものです。CoffeeScriptのデザイン自体も非常によくできていました。本当に出来がいい。
実は今でも書いている人がいるらしいんですよ(笑)。小耳に挟んだ話だと、あるチームではメンバーの大多数が「今回はCoffeeScriptでやろう」という話になっていたらしいんですが、コード生成ツールを使っているメンバーが「TypeScriptのコードしか出力できないですよ」と言い出して、仕方なく、最終的にはみんなでTypeScriptに落ち着いた、という話があったようです。
4. JSX — S式の再来とLISPの遺伝子
👤 司会:
今でこそJSXは当たり前の書き方として認識されていますが、元来のJavaScriptからしたらかなりトリッキーに見えたのではないかな?と想像します。JSXについては、どのように感じられていましたか?
💡 北條:
JSXのすごいところは、LISPの設計思想を彷彿とさせる点です。
LISPでは括弧を大量に使いますが、データもプログラムも同じS式(S-expression)という記法で表現でき、同じように処理できるように設計されています。つまり、「どこまでがデータで、どこまでがプログラムか」という境界を、開発者が自由に調整できるのです。見た目としては括弧だらけの記法でひたすら書くだけなのですが、「これはデータです」として記述していたものが、処理の文脈によってはプログラムとして実行されることも普通にできます。
で、Brendan EichがJavaScriptを作ったときに、「見た目はC言語というかJava風にしろ」という指示が入っちゃったから、S式は全部捨てざるを得なかった。にもかかわらず、JavaScriptはLISPにルーツを持っている。
プログラミング言語って、S式を捨てているものは本当に多くて、JavaScript以外にもたくさんあるんだけど、S式が持っている "プログラムとデータの境界を曖昧にできる自由度" は失われていたんですよね。でも、JSXが入ったおかげで、また「どこまでがプログラムで、どこまでがデータなのか」をはっきりと分離した記法で書けるようになった。少なくとも見た目が違うから、ここがデータでここがプログラム、というのが明確になったし、そういう書き方が戻ってきたのは大きい。
今までは、JavaScriptに限らず他の言語でもそうだけど、「これはデータ? プログラム?」みたいなものを文字列で組み立てて、それをパースして前処理して……といった面倒なことをやらなきゃいけなかった。でもJSXならそういうことが自然に扱える。
で、JSXが出てきたときも、「S式っぽい自由度を持つ仕組み」にいろんな言語がチャレンジしては失敗してきたのを見ていたから、「まあ今回もダメなんだろうな」と思っていたんですよ。あまり期待せずに見ていたんだけど、実際に触ってみると「いや、すごくよくできてるじゃん」と思った。そんなに精緻な仕様でもないのに、書いてみると自然に書けて、苦労しないように設計されている。すごくバランス感覚のいい人が作ったんだなと感じました。
👤 司会:
JSXが最初出てきた時は「JavaScriptの中にHTML書くなんて気持ち悪い」みたいに否定的な声もあがったという話も聞いたことがありますが、そういうふうには感じなかったのですか?
💡 北條:
ないね。書けて当たり前。なぜ書けないのかがむしろイライラしていたので。すごくいい仕事した人がいるんだなと思って。大変嬉しかったのだけ覚えています。
5. TypeScript — 静的型付けのトレードオフ
👤 司会:
世の中的には「TypeScript大正義」というような風潮であり、ピュアなJavaScriptではなくTypeScriptを導入するプロジェクトが多いですよね。ただ一方で、「TypeScriptって微妙じゃない?」というような意見も一部ネットでたびたび見かけ、個人的には一定の説得力を持っているようにも見えます。自分も、TypeScriptの恩恵は感じながらも、「型パズルがちょっとしんどい」「TypeScriptのためのツールを色々用意するのが面倒」などとネガティブに感じることも正直あり。
💡 北條:
特に、JavaScriptであれば柔軟に扱える場面で、静的型付けが逆に負担になることがあるんですね。たとえば、あるデータを処理するプログラムがあったときに「共通処理をまとめられそうだな」などと思ったとします。生のJavaScriptであれば、オブジェクトに後から関数プロパティをポンってくっつければ、簡易的にメソッド化するといった試行錯誤が容易にできるじゃないですか。すごく巨大なアプリケーションの中で、こういう決められた範囲の中でちょっと試してみるっていうのが簡単にできるんですよね。
しかしTypeScriptや、より厳格な静的型付け言語のアプローチを採用すると、実験的に設計を変えたいだけでも追加の作業がたくさん必要になります。
具体的には:
- クラス化するなら
constructorを定義する - プロパティの型情報を明示的に宣言する
- 外部との契約を表す
InterfaceやTypeを事前に記述する必要がある - 型の整合性のために修正箇所が多岐に及ぶ
といった形で、「ちょっと試してみる」という作業にも型体系に合わせた準備が要求されがちで、ちょっとしたことを気軽に試せなくなっているんですね。
昔と違って、今は生のJavaScriptも標準化されてきちっと動き、トランスパイラー不要みたいな状況になってきているので、そういう意味ではTypeScriptを使って嬉しいっていうのは、個人的にはあまりないんですよね。だから、興味もあまりなくなっちゃった。
昔だったらCoffeeScriptで書いてましたけど、今はわざわざCoffeeScriptを走らせる環境を用意するほどじゃないなっていう感じになったんで、そんなにTypeScriptとかに惹かれる事も無くなってきています。
全てTypeScriptにするとかじゃなくて、静的型言語が得意とするロジカルで強固な部分を TypeScriptで書いて、フワッとしていて要件とかもあまり明確化出来ていないところをJavaScriptで書けるようなプロジェクト構成で開発出来ると良いと思います。
📅 JavaScript技術年表 — 本記事で登場した技術たち
※ 本年表はインタビュー内容の理解を助けるための参考情報です。詳細な歴史については公式ドキュメントや一次資料をご参照ください。
本記事で北條さんが言及した技術について、歴史的な背景をまとめました。
XMLHttpRequest / Ajax
| 項目 | 内容 |
|---|---|
| 登場年 | 1999年(Internet Explorer 5に実装)/ 2005年頃「Ajax」として注目 |
| 開発者・組織 | Microsoft(ActiveXオブジェクトとして実装した) |
| 当初の目的 | OutlookのWeb版でページ遷移なしでサーバーと非同期通信を行う |
| 解決した課題 | フォーム送信やリンククリックのたびにページ全体をリロードする必要があった |
| 現在の位置づけ |
fetch() APIに主役の座を譲りつつも、レガシーコードでは現役 |
| 影響を与えたもの | Gmail、Google Maps(2004-2005)の登場で「Ajax」という概念が確立。SPAの礎を築いた |
「Ajax」という名前の由来
2005年に登場したGoogle MapsやGmailは、XMLHttpRequestを利用した革新的なUIを実現しました。これについてUXデザイナーのJesse James Garrettは「Ajax: A New Approach to Web Applications」という記事を公開し、「ページ遷移なし、非同期でのデータ取得、JavaScriptによる画面描画」という手法を「Asynchronous JavaScript and XML」の頭文字をとったAjaxと名付けました
CoffeeScript
| 項目 | 内容 |
|---|---|
| 登場年 | 2009年12月13日(初コミット)/ 2010年12月24日(v1.0.0リリース) |
| 開発者 | Jeremy Ashkenas (Backbone.js, Underscore.jsの開発者) |
| 当初の目的 | JavaScriptの冗長な構文を簡潔にする |
| 解決した課題 | ボイラープレートコードの削減、クラス構文やアロー関数的記法の先取り |
| 現在の位置づけ | ES6+とTypeScriptの普及により利用は減少。 |
| 影響を与えたもの | ES6のアロー関数(=>)、分割代入、クラス構文、テンプレートリテラルなど多くの機能に影響 |
CoffeeScriptの遺産
北條さんが「CoffeeScriptが出てきたときには飛びついた」と語るように、当時のJavaScript開発者にとって救世主的存在でした。Ruby、Python、Haskellからインスピレーションを受けた構文は、後のECMAScript標準化に大きな影響を与えました。
JSX
| 項目 | 内容 |
|---|---|
| 登場年 | 2013年(React公開と同時) |
| 開発者・組織 | Facebook(現Meta)/ Jordan Walke |
| 当初の目的 | UIを JavaScript の中で “関数的・宣言的” に記述できるようにするため、UI構造を自然に表現できる文法を提供すること。 |
| 解決した課題 | テンプレートとロジックの分離による複雑さ、DOMの手動操作 |
| 現在の位置づけ | Reactエコシステムの中核として広く普及。(Solid.js、Preact、Bunなど) |
| 影響を与えたもの | コンポーネントベース開発の標準化、宣言的UI記述の普及。 |
北條さんの視点:S式の再来
北條さんは「JSXのすごいところは、LISPの設計思想を彷彿とさせる点」と評しています。データとプログラムの境界を明確に分離しつつ、柔軟に扱える点がLISPのS式に通じるという見解は、JavaScript(Scheme由来)のルーツを知る北條さんならではの洞察ですね。
TypeScript
| 項目 | 内容 |
|---|---|
| 登場年 | 2012年10月1日(v0.8公開) |
| 開発者・組織 | Microsoft / Anders Hejlsberg(C#、Delphi、Turbo Pascalの設計者) |
| 当初の目的 | 大規模JavaScript開発における型安全性とツールサポートの向上 |
| 解決した課題 | 型エラーの早期発見、IDEによるコード補完・リファクタリング支援 |
| 現在の位置づけ | フロントエンド・バックエンド問わず、JavaScript開発のデファクトスタンダード |
| 影響を与えたもの | 静的型付けAltJSの主流化 |
北條さんの視点:柔軟性とのトレードオフ
北條さんは「静的型付けが逆に負担になることがある」と指摘しています。JavaScriptの柔軟性を活かした素早い試行錯誤が、型定義の追加作業によって阻害される場合があるという視点です。「静的型言語が得意とする部分をTypeScriptで書いて、ふわっとしているところをJavaScriptで書ける構成が良い」という提案は、実務的なバランス感覚を示しています。
ES Modules(補足)
| 項目 | 内容 |
|---|---|
| 登場年 | 2015年(ES6/ES2015で標準化) |
| 開発者・組織 | Ecma International / TC39 |
| 当初の目的 | JavaScriptの公式モジュールシステムを標準化する |
| 解決した課題 | グローバル汚染、依存関係管理、名前空間の衝突 |
| 現在の位置づけ | ブラウザ・Node.js両方でネイティブサポート。現代JS開発の基盤 |
| 影響を与えたもの | CommonJS、AMD、UMDといった過去のモジュールシステムを統一 |
IIFEからES Modulesへ
北條さんが語った「ファイルの頭と末尾をfunctionで包むおまじない」は、ES Modules登場以前の必須テクニックでした。import/exportの標準化により、こうした手動の名前空間管理は不要になりました。
年表サマリー
1995年 ─ JavaScript誕生(Brendan Eich、Netscape)
│
1999年 ─ XMLHTTP実装(IE5)
│
2004-2005年 ─ Gmail/Google Maps公開、「Ajax」命名
│ └ Webアプリケーションの革命
│
2009年 ─ CoffeeScript登場
│ └ 「綺麗なJavaScript」への道
│ └ Node.js登場(サーバーサイドJS)
│
2012年 ─ TypeScript公開(Microsoft)
│
2013年 ─ React/JSX公開(Facebook)
│ └ コンポーネント指向とVirtual DOM
│
2015年 ─ ES6/ES2015標準化
│ └ クラス、アロー関数、ES Modules
│ └ CoffeeScriptの多くの機能が標準に
│
現在 ─── TypeScript + React/Next.js が主流
⚠️ 免責事項
本記事は、社内イベントを基に作成したものです。以下の点にご留意ください:
- 記事内容は対談者個人の経験と見解に基づいており、所属組織の公式見解ではありません
- 技術的な情報については正確性の確保に努めておりますが、記憶に基づく内容も含まれるため、情報の正確性・完全性を保証するものではありません
-
JavaScriptや関連技術は日々進化しており、記事執筆時点での情報となります - 本記事の情報を利用して生じた損害について、執筆者および所属組織は一切の責任を負いかねます
- 正確な情報が必要な場合は、公式ドキュメントや一次情報源をご確認ください