プログラミング初心者のための JavaScript と Node.js の歴史、それを踏まえた勉強方法
2020年でJavaScript学ぶならきっとブラウザ向けJSガン無視していきなり初手node.js(ただし暫く何も足さない)がいいんじゃないかというメモ - min.t (ミント)
Node.js を教えることについて、自分は賛成なんですが、その学習パスが整理されてないなと思っていたのと、学習パスがなぜ整理されていないかについて書きます。
はじめに
問題意識として、今のプログラミングスクールや独学勢が Ruby on Rails に偏っていて、 Node.js の人間としては、歯がゆく感じているんですが、実際 Node.js を教えるとしても問題も多いと認識しています。
歴史の話は、当時の実情や政治を省いて結果だけを書きます。具体的には第一次ブラウザ戦争、第二次ブラウザ戦争を言及しません。
歴史
NetScape という古のバージョンに搭載された、ブレンダン・アイクの最初のJavaScriptがありました。本人曰く、二週間のやっつけで作ったものらしいです。こいつが使われるようになって、HTML を動的に動かすための言語の標準を決めようという話になりました。
そこで、ECMA という団体でプログラミング言語としての標準仕様を決めました。その仕様が ECMAScript (ECMA 262) で、その実装が今日知られている JavaScript という言語です。
ここでいう ECMAScript は言語としての機能だけを決めており、ウェブブラウザとしての機能は言語に含まれません。具体的には、 window や document に属するものは、ECMA 262 としては何の関係もありません。その辺は W3C という別の組織で行われることになっています。
NetScape の資産は Mozilla に引き継がれたのですが、結果的に Internet Explorer が一番使われるようになった、という事情などを背景に、JavaScript の基本的な性格が決まっていきます。
すなわち、JavaScript の言語的な性格として、主流となる実装を参照して仕様が決まるのではなく、仕様が先にあって、それぞれがその仕様に従いながら、速度改善など独自の拡張を施す、というものです。
この ECMA 262 という仕様に従って、他のブラウザでも JS Engine が実装されました。
- Internet Explorer Chakra
- Chrome V8
- Firefox spider Monkey
Node.js とは何か
この中で、 Chrome に搭載された V8 Engine がとても優秀だったので、これを java, ruby, python と同じくサーバーサイドの言語として使おうとしたのが Node.js です。
ここでいう、サーバーサイドの言語、というのは以下の特性を持ちます。
- HTTP/HTTPS などのネットワークリクエストを処理できる
- ファイルの読み書きができる
V8 自体は ECMA 262 の範疇に従った実装で、それ以上ではありません。 Chrome のブラウザとしての機能の提供は Blink というモジュールで提供されます。
ライアン・ダールは、このうち V8 だけを使って、つまり ECMAScript としてサーバーサイドの言語に必要な機能を足しました。それが Node.js です。彼が JavaScript を使ったのは、 JavaScript が好きだったから…ではなく、一本のスレッドで大量のリクエストを捌くイベントドリブンというサーバーアーキテクチャに適している言語だという理由です。
しかし、Node.js はイベントドリブンの実現のものというより(その用途も広がりましたが)、汎用的なスクリプト言語として発展します。とくに元々は Ruby,Python,Perl が担っていた書き捨てのスクリプトや、フロントエンドのためのツールチェインを記述するものになっていきました。とくに言語成立経緯から自分自身の言語仕様が厳密に決まっている言語なので、言語処理系に関するライブラリが多く、中には TypeScript という、言語拡張すらあります。
npm というパッケージマネージャ兼ホスティングサイトが node 本体に組み込まれ、ライブラリエコシステムが発展することになります。これが今日の Node.js というもので、これが、「なぜ JavaScript が Python などと比較されるのか」という tricken さんへの答えになります。
JavaScript を学ぶことの利点
クライアントとサーバーで一つの言語で同じ仕様(ECMA 262) なので、一度学んだものを学び直す必要がなく、学習効率がいいです。もちろん、それぞれの実行環境ごとに提供される機能が違いますが、文法がガラッと変わってしまうほどのものではないので、一度学んだ文法で別の実行環境を学ぶ、という体験になります。RubyとJSだと違うプラットフォームのために2つの言語を覚える必要がありますが、JSだと同じ言語で違うライブラリを覚える、ぐらいの感覚です。
言語の速度的にも、Nodeの V8 は十分速いです。同じアルゴリズムを記述した時、 C言語 を 1 として、 JavaScript が 4~8, Ruby Python が 15~25 というのが自分の肌感です。
kostya/benchmarks: Some benchmarks of different languages
言語機能的にも、2015年からは毎年言語の仕様が更新されることになり、(過去のやっつけ感がなんだったのかというくらい)とても洗練された議論、文法定義、セマンティクス定義が行われており、最近でも async/await や dynamic import のような先進的な仕様が勧告されては、モダンブラウザはそれを参考にこぞって実装する(半年~2年)、という状態です。
JSに習熟していった先の発展的な進化として TypeScript を使うと、JSに型システムを導入することができます。型がないから駄目だ、みたいなことを言う人も多かったですが、TypeScript は動的型から静的型にシームレスに移行できる言語で、はじめての静的型言語の学習コスト的にも、適切です。
ビジネス視点で言っても、JavaScript を学んだ人間はウェブに関わる限り必ず必要になるので、潰しが効きます。
とにかくユーザー層が厚いので、新しい概念やプラットフォームに対して、ライブラリが生まれる速度、そして枯れる速度が速いです。今できないことも、半年待ってれば可能になってることが多いです。
JavaScript の学びにくさ
捨てられない負債 - 後方互換性
今では負債となった言語的な挙動を捨てることができていません。具体的には、 typeof null => 'object'
という挙動や、 ==
の比較演算子の理解に苦しむ挙動です。
TC39, ECMAScript の仕様決めるグループの方針として、後方互換性を維持する、つまり過去に作られたウェブサイトを壊さないという方針があります。JavaScript のアップデートによってウェブサイトが壊れてしまうと、インターネットという基盤自体が文書を保存するのに信用されないものと捉えられてしまう可能性があります。それは避けたいので、過去の負債を捨てることができていません。
比較的新しい Node.js でも ベースがES2015以前の設計なので、根幹となるモジュール設計に common.js という仕様が採用されたままです。 require('fs')
みたいなやつです。これと import fs from 'fs'
が、実行環境によって同じように動いたり動かなかったりするのですが、それについて語りだすと長くなってしまうので、ここでは語りません。
Promise と async await は今の非同期処理の根幹を支えるベースなのですが、Node.js の標準ライブラリの多くが、未だコールバックという古いスタイルのままです。
そのあたりの問題があります。
信頼できない過去の資料
JavaScript に関係する人はほぼWebの開発者と等しいため、Node.jsだけではない、様々なスキルをもった開発者がいます。JSがメインでない、習熟度が低い人も多く触る言語なので、ネット上には信頼できない学習資料が多々あります。
Node.js の普及以前(~2010)のJSの資料は、 当時デファクト的な立ち位置だった jQuery の機能と、言語としての基本機能を混同した資料が多いです。 今では、 $
の文字を見たらもう参照してはいけない、ぐらいの気持ちで臨まないといけないです。
この点で jQueryを前提とするプログラミングスクールの学習カリキュラムに危機感を感じています。古いJSを覚えた人が大量に界隈に放たれることで、フロントエンド全体の方向性として下方圧力になる、という危惧です。
jQuery が実際に選ばれる理由は、プログラミングスクールの人達の組成が RoR だという以上の理由はあまりないとは思っているんですが…
Stackoverflow も駄目です。古いものが多いのと、最近でもヤバいコードがベストアンサーになる率が高いです。
具体的には、最低でも ES2015 を参照したと書かれている 2015年以降の資料、可能なら2年以内の記事を参照するようにしてください。
ベストプラクティスの不在
ES2015は決定版だったので、これをターゲットにした資料は比較的多めなのですが、それ以降の資料の更新が、全体的に断続的なものとなっています。フロントエンドコミュニティの中にふんわりと共有されてるという状態で、それがまとまった資料や書籍などがありません。
これによって、学習資料の決定版の不在、という問題があります。その問題に対して、とりあえず今は JS Primer を推奨しています。
JavaScript Primer - 迷わないための入門書 #jsprimer
ただ、この本自体は、「プログラミングの基礎を抑えた人がJSを学び直す」という位置付けで、内容的にもリファレンスなものなので、ある程度学ぶ意思がある人に対してしか応えられていません。初学者がこの本を読むまでには、別の資料が必要になるでしょう。
自分はプログラミング初学者の気持ちを忘れてしまって久しいので、この件については、自分の周りで入門として評判がいいのは、N予備校のプログラミングコースです。
ちょっと古い記述はありつつも(更新されているのかな?)、かなり体系的に身につけられる…らしいです。
これについて、自分で JS Primer に足りないものを補う本を昔から書きたいという構想があるのですが、界隈が流動的なのでなかなか踏み切れていませんでした。ただ、そろそろかなと思っています。
中級者向け学習資料
ある程度わかってきたら、最近の話題のニュースや GitHub のトレンドをみて、自分の興味を確認したり、何をやるか決めると良いでしょう。具体的にはこの辺りです。
- JSer.info
- Trending JavaScript repositories on GitHub today
- Trending TypeScript repositories on GitHub today
自分は、一時期GitHubのTrendingに上がってくるリポジトリののExampleを片っ端から動かすみたいなことをしていました。これは無茶苦茶勉強になりましたが、体力を使います。
日本のフロントエンド界は azu さんに支えられています。これはネタでもなんでもなくマジです。僕は今これがはやろうとしているぞ、みたいなポインタを示す係です。
まとめ
- 初心者は N予備校、JS Primer でキャッチアップして、中級者以降は jser.info や GitHub Trending を眺めるのがオススメ
- このへんをキャッチアップする本を書きたいけど構想段階
Discussion