- 説明のプロではありません。
- 理解しづらいところは都度突っ込んでOK
- #深層フロントエンド で実況OK
- 分かりやすさ優先のため、わざと曖昧に言うことがあります。
注意書き
いざ深層へ
機械語=バイナリを解釈
文字列は解釈できない
JavaScriptプログラム=文字列を解釈し、CPUに実行させる。
V8, SpiderMonkey, など
JSコーダーがお世話になるのはJSエンジンではない。
⇒ 他のものに組み込まれた状態で使っている。
ブラウザ:scriptタグに書いたJSが動く
Chrome→V8 Firefox→SpiderMonkey
Node.js:.jsファイルが動く
→V8
JavaScript文字列をパース(分解)して、
ここは足し算だ、ここは変数宣言だ、ここは関数呼び出しだ
を解釈・実行するだけ。
これだけでは何のアプリケーションも作れない
ブラウザ:HTMLの操作機能等
= windowオブジェクト
Node.js:ファイルの読み書き機能等
= require('fs')
これを用意しているのがJS環境
JSエンジン
JS環境
.js
V8
Node.js
Node.js用.js
V8 / SpiderMonkey
Chrome / Firefox
ブラウザ用.js
ブラウザで動くJS=ブラウザ向けJS環境には
どんな機能が必要か?
→ window.document HTML(DOM)をいじる
→ window.location 現在のURLを取得・操作
→ window.localStorage 簡易データ保存領域
ブラウザ間で仕様の統一が進められている
他の言語が持つ「標準ライブラリ」相当のものを用意
・ ファイルの読み書き
・ ネットワーク通信(TCP・UDP)
・ プロセスの制御
JavaScriptが他の言語と同格になった
例えば配列のforEach
console.log('A')
const array = [1, 2, 3]
array.forEach(function (value) {
console.log(value)
})
console.log('B')
関数は
すぐに
呼び出される
A
1
2
3
B
buttonがクリックされたら
console.log('A')
$('button').on('click', function (event) {
console.log('clicked!')
})
console.log('B')
関数は
クリックする度
呼び出される
A
B
clicked!
clicked!
clicked!
setTimeout
console.log('A')
setTimeout(function () {
console.log('timeout!')
}, 1000)
console.log('B')
関数は
1秒後に
呼び出される
A
B
timeout!
別の場所で呼び出されるような関数のこと。
『いつ』呼び出されるか?
『何回』呼び出されるか?
実行の順番・タイミングに注意
executeJavaScriptProgram()
while ( eventHandlers.length ) {
executeTriggeredHandlers()
}
まず最初に
記述されたJSを
1度だけ実行する
イベントハンドラが
登録されている状態
executeJavaScriptProgram()
while ( eventHandlers.length ) {
executeTriggeredHandlers()
}
イベントハンドラが
1個以上あるならば
ループする
executeJavaScriptProgram()
while ( eventHandlers.length ) {
executeTriggeredHandlers()
}
登録されたハンドラのうち
イベント
= クリック
= 時間
が発火したものを実行する
executeJavaScriptProgram()
while ( eventHandlers.length ) {
executeTriggeredHandlers()
}
イベントハンドラが
なくなったら
ループを終了する
= プログラムが終了
executeJavaScriptProgram()
while ( eventHandlers.length ) {
executeTriggeredHandlers()
}
Input/Output = 入出力
→ console.log()
→ ネットワーク
→ ファイル
URLにリクエストを送信
↓
レスポンスが
帰ってきたら
"done!"
console.log('A')
$.get('http://oro.co.jp', function (html) {
console.log('done!')
})
console.log('B')
URLにリクエストを送信
↓
レスポンスが
帰ってきたら
"done!"
console.log('A')
const html = $.get('http://oro.co.jp')
console.log('done!')
console.log('B')
同期I/O:レスポンスが帰ってくるまで待つ
= イベントループが止まる
= 他の処理が実行されない
= (ブラウザの場合)操作ができなくなる
非同期I/O:レスポンスが帰ってきたらコールバック
= イベントループが止まらない
= 他の処理が実行できる
= (ブラウザの場合)操作できる
JSのコードを複数のファイル=モジュールに分割
モジュールが他のモジュールを読み込む
→ 他のモジュールに書かれた関数を使える
JSの言語仕様としてのモジュールシステム
export ......
export default ......
import ...... from './path/to/file.js'
import * as ...... from './path/to/file.js'
ES Modulesが策定される以前から
JSの様々な標準化を行っているプロジェクト
CommonJS式モジュールシステム
module.exports = ......
const ...... = require('./path/to/file.js')
これらのモジュールシステムでは、
ファイルが分かれることで「スコープ」が分かれる。
= 変数名・関数名の被りを気にしなくてよい。
カプセル化によって見通しが良くなる。
= 意味や役割によってコードを分割でき、読みやすい。
= 依存関係の明確化。不要なコードを捨てやすい。
これらのモジュールシステムが使われたコードは
そのままではブラウザで動かない
変換ツール
- browserify
- babel
- rollup
- webpack
複数のブラウザで動くようなJSコードにするには
「ES5」仕様に合わせる必要がある。
もちろんモジュールシステムを使うことはできない。
開発環境 ←→ 動作環境
の差異を埋める処理が「ビルド」
CommonJS式モジュールシステムで書かれた
複数のファイルを結合して、
ブラウザでも動作するように変換するライブラリ。
→ ブラウザアプリケーションを
モジュールシステムを使って開発できるようになった。
ES6, ES7に存在する新しい文法で書かれたコードを
ES5, CommonJS仕様のコードに変換してくれる
例)spread operators, async functions
→ ブラウザアプリケーションを
新しい便利な記法で書けるようになった。
ES Modulesで書かれたJSファイル群を
最適化しつつ、ブラウザで動く形式に結合してくれる。
「loader」という仕組みを導入することで
JSのモジュールシステムを使って
JS以外のファイルを読み込めるようになる。
ブラウザアプリケーションに必要なアセットの読み込みを
モジュールシステムを使って行うような記述が可能になった。
特に画像やCSS
Vue.js、React、Angularのアプリケーションでは、
用意されたScaffoldingツールを使うことで、
ビルドに関する作業を全く気にしなくて良くなった。
内部でwebpackが用いられているので
知っておく分には◎
つづく