「長い旅にはカバンより歌のほうがうれしいものだよ」
-- トーベ・ヤンソン:『さびしがりやのクニット』
読んだまとめ
JSの全体像が見えた気がする。ハンズオンで実際にコードを書くので頭にも入りやすかった。ただ分厚いので時間はかかった。
1章 学び始める前に
JavaScriptの基礎的な説明
2章 データを学ぶ
JavaScriptの基礎的な説明
3章 処理を学ぶ
- アルゴリズムとは「何らかの解を得るための手順」のこと。
- 式は文の一種で値を返すが、文は必ずしも値を返さない
-
let pi = 3.14
- 文
-
- ブロック
{}
- 変数や定数のスコープができる
- そのブロックのみで有効となる
- 変数や定数のスコープができる
4章 オブジェクトを学ぶ
- JSのオブジェクトは単なるキーバリューのペアではなくメソッドも定義できる
5章 モジュールを学ぶ
-
true.toString()
はプリミティブなのになぜできるのか- 対応するオブジェクトに自動変換されるから
- ボックス化と呼ばれる
- 明示的に相互変換するには
- オブジェクトにする
new Object(true)
- プリミティブにする
Object(true).valueOf()
- オブジェクトにする
- 対応するオブジェクトに自動変換されるから
6基本的な標準オブジェクトを学ぶ
- falsyな値
- false
- null
- undefined
- 0
- 0n
- ''
- NaN
- 数値のプロパティアクセス
-
42.toString()
はエラーになる- ドットを二つでアクセスできる
42..toString()
- ドットを二つでアクセスできる
-
- Well-Known Symbol
Symbol.hasInstance
Symbol.toPrimitive
Symbol.toStringTag
- Functionオブジェクト
- apply() は引数を配列で受け取る
add3.apply(1, [16, 25])
- call() は個別に受け取る
add3.call(1, 16, 25)
- bind() はthisや引数の値を固定した関数を新たに作る
-
bind(1)
ならthisは1となる
-
- apply() は引数を配列で受け取る
- RegExp
- オプションフラグ
- g
- 一致した文字列を全て返す
- i
- 大文字小文字を無視する
- m
- 複数行検索する
- g
- 文字列メソッドで正規表現を利用する
-
search()
- 見つかったら位置を、見つからなかったら
-1
を返す
- 見つかったら位置を、見つからなかったら
-
match()
- 見つかったらその文字列を、見つからなかったら
null
を返す
- 見つかったらその文字列を、見つからなかったら
-
matchAll()
- 見つかったらイテレータを返す
-
split()
- 正規表現に一致する部分で分割して配列を返す
-
replace()
- 置き換えて返す
-
- オプションフラグ
# 7章 コレクションを学ぶ
- Array
-
Array.from(days, i => i * i)
- 二乗したものを配列にできる
-
includes(3, 1)
- 第二引数の位置から確認を始める
-
some(n => 4 < n)
- 条件式を満たす要素があるかどうか確認する
-
every(n => 0 < n)
- 配列の全ての要素が条件式を満たすか確認する
-
reverse()
- 破壊的メソッド
-
sort()
- 破壊的メソッド
- デフォルトでは数値比較ではなく辞書順
-
entries()
- 要素とインデックスが両方必要な時に使う
-
flat(2)
- 引数で平坦化する深さを指定する
-
[1, 2, 3].reduce((sum, n) => sum += n, 0)
- 最後の引数は初期値
- 初期値は省略しない方がいい
- 空配列の場合 TypeError が発生する
- 要素が一つの場合コールバック関数が実行されない
- 初期値は省略しない方がいい
- 最後の引数は初期値
-
- 配列をスタックのように扱う
-
stack.pop()
-
stack.push()
-
- 配列をキューのように扱う
-
queue.shift()
-
queue.pop()
-
- 配列をスタックのように扱う
-
- Map
- キーによって要素を管理するとき使う
- オブジェクトでは
obj[1]
とobj["1"]
は区別されないが、マップでは区別される - MapやSetはブラケット記法やドット記法ではアクセスできない
- ☠️
map.key
- プロバティへのアクセスとなる
- ☠️
-
forEach()
で回すときは値が先に渡される- map.forEach((v, k) => console.log(
key: ${k}, value: ${v}
))
- map.forEach((v, k) => console.log(
- メモリ管理
- JSが管理するメモリ
- スタック
- プリミティブを保持しているローカル変数が使用する
- 型ごとに必要なメモリ容量が決まっている
- オブジェクト
- どこに保存しているかの情報のみ
- これを参照と呼ぶ
- メモリ容量は固定
- オブジェクトは容量固定ではないから
- 実際のデータはヒープに保存する
- これを参照と呼ぶ
- どこに保存しているかの情報のみ
- プリミティブを保持しているローカル変数が使用する
- ヒープ
- ガベージコレクションされる
- 例として参照カウント
- カウント0になったら利用なし
- 解放される
- 弱参照はカウントされない
- 解放される
- カウント0になったら利用なし
- 例として参照カウント
- ガベージコレクションされる
- スタック
- JSが管理するメモリ
- WeakMap
- 弱参照
- 元オブジェクトの生成や取得に時間がかかる場合の付随情報を管理する使い方など
- Mapだと元オブジェクトが消えても参照され続ける
- 元オブジェクトの生成や取得に時間がかかる場合の付随情報を管理する使い方など
- 弱参照
- Set
- 値を一意に保持するだけの時に使う
-
[...new Set(days)]
で days の重複を取り除ける
-
- 値を一意に保持するだけの時に使う
- イテレータ
-
next()
メソッドを持ったオブジェクトの総称- 戻り値は
value
とdone
を持つオブジェクト-
done
でまだ要素が残っているかどうかがわかる
-
- 戻り値は
-
- イテラブル
- 反復可能かどうか
- そのオブジェクトが
Symbol.iterator
キーとするプロパティを持つかどうか-
for-of
は与えられたオブジェクトの[Symbol.iterator]メソッドを呼び出してイテレータを取得し、そのイテレータのnext()メソッドの呼び出し結果の done が true になるまで、next()を呼び出し value の値を変数に代入して、その変数を使用した処理を繰り返し実行している-
for-of
できるオブジェクトは全て[Symbol.iterator]
メソッドを持つ- 自分自身を返す
[Symbol.iterator]
メソッドがある
- 自分自身を返す
-
-
- そのオブジェクトが
- 反復可能かどうか
for (
let iter = obj[Symbol.iterator](), rslt = iter.next(), item = rslt.value;
!rslt.done;
rslt = iter.next(), item = rslt.value
) {
console.log(item)
}
- ジェネレータ関数
- イテレータかつイテラブル
- 関数実行するとジェネレータオブジェクトを生成して返す
- イテラブルなので
for-of
文で反復実行できる
- イテラブルなので
- 関数実行するとジェネレータオブジェクトを生成して返す
-
function*
や*method(){}
で作成する- 関数定義の本文を
next()
で実行する- return に到達するとそれを
{value: "1200kVA", done: true}
オブジェクト戻り値として返す- だがnext()が常に
done:true
だと繰り返せない-
yield
を処理を一時中断するreturnとして使う-
done:false
となる
-
-
- だがnext()が常に
- return に到達するとそれを
- 関数定義の本文を
- メソッド
-
next()
- 引数をひとつ取れる
-
再開された二度目以降の yield式の戻り値となる
- 最初に渡した引数は無視される
-
再開された二度目以降の yield式の戻り値となる
- 引数をひとつ取れる
-
return()
- 処理の再開と同時に繰り返しを終了する
- 与えた引数は戻り値の value の値に入る
- 処理の再開と同時に繰り返しを終了する
-
throw()
- 処理の再開と同時に例外を発生する
-
- イテレータかつイテラブル
複雑なデータの扱いを学ぶ
- バイナリデータ
- 2進数で表現されたデータ
- まずデータをそのまま保持する
- ArrayBuffer オブジェクトを使う
- バッファのサイズ(byte)を引数にする
- ほとんど保持する機能だけ
-
.byteLength
でバイト数を読み取れる -
slice(start, end)
で切り取ったコピーを作れる
-
- ArrayBuffer オブジェクトを使う
- 読み書きは別オブジェクトを使う
- ビュー
- 型付き配列(TypedArray)
- 特定の型を持つバイナリデータに配列形式でアクセスするオブジェクト群の総称
- コンストラクタにArrayBufferオブジェクト以外の引数を与えると内部的に ArrayBufferオブジェクトを生成する
- 特定の型を持つバイナリデータに配列形式でアクセスするオブジェクト群の総称
- DataView オブジェクト
- さまざまな型のデータにアクセスできる
set<Type>()
get<Type>()
- 明示的にエンディアンを指定できる
- リトルエンディアンは
true
- リトルエンディアンは
- さまざまな型のデータにアクセスできる
- 型付き配列(TypedArray)
- ビュー
- JSON
-
JSON.parse(42, reviver)
- 第二引数で変換処理をする関数を渡せる
- オブジェクトを文字列やバイト列に変換すること
- 直列化やシリアライズと呼ばれる
-
JSON.stringify(obj)
もその一つ- 列挙可能(enumerable)でないプロバティはJSON文字列に含まれない
-
toJSON()
メソッドがあるとそれが使用される -
JSON.stringify(obj, replacer)
でJSON文字列変換前に Array[0] だけを取得するなどの処理ができる - 第3引数にはインデント指定できる
-
let obj2 = JSON.parse(JSON.stringify(ko1))
で1行でディープコピーできる
-
- 直列化やシリアライズと呼ばれる
-
国際化を学ぶ
- i18n
- 言語や時間、数値の表記の違いを吸収する
- Date
-
new Date(1868, 3, 4)
- 4月となる
- 月だけが0から始まる
- 4月となる
Intl.DateTimeFormat
-
非同期処理を学ぶ
- 処理の流れをスレッドと呼ぶ
- JSはシングルスレッド
- 非同期処理
- コールバック関数
- 相手の都合のよいタイミングで電話を「かけ直して」もらう
- Buttonオブジェクト
-
addEventListener()
でコールパック関数を設定する- 処理するのはイベントハンドラやイベントリスナ
-
- 何度も発生するイベントをその都度処理するのに適している
- 一般的な非同期通信に適した手法ではない
- コールバック地獄
- Promise が解決してくれる
- コールバック地獄
- 一般的な非同期通信に適した手法ではない
- Promise
- その処理が完了していなくても即座にPromiseオブジェクトを返してくれる
- 完了後の処理を then()メソッドの引数として与えられる
- Promiseは実行結果を保持している
- 実行完了後にthen()メソッドを使う
- 連結するとPromiseチェーンとなる
- 実行完了後にthen()メソッドを使う
- Promiseは実行結果を保持している
- 完了後の処理を then()メソッドの引数として与えられる
- その処理が完了していなくても即座にPromiseオブジェクトを返してくれる
- コールバック関数
function waitFor(msec) {
return new Promise(resolve => {
setTimeout(resolve, msec)
})
}
waitFor(Math.random() * 5000).then(() => {
console.log("処理A")
return waitFor(Math.random() * 5000)
}).then(() => {
console.log("処理B")
return waitFor(Math.random() * 5000)
}).then(() => {
console.log("処理C")
})
- catch()メソッドを使うときは then()メソッドでは第二引数を使わない
> Promise.resolve().then(() => console.log("Promise内"))
console.log("Promise後")
Promise後
Promise内
- 常に then()メソッドのコールバック関数があとに実行される
- 非同期処理はいつ完了するかわからない
- 完了タイミングで挙動が変わると動作が不安定になる
- 後実行の挙動が保証されている
- 完了タイミングで挙動が変わると動作が不安定になる
- 非同期処理はいつ完了するかわからない
- 複数の非同期処理をまとめて扱う
Promise.all
-
Promise.allSettled
- 一部失敗しても全体は失敗しない
- then() で結果を受け取ることができる
-
Promise.race
- 最初に完了するPromiseだけが最終結果に影響を与える
- async関数
- return文で値を返せば成功したPromiseが、throw文で例外を発生させれば棄却されるPromiseが返る
- 非同期イテレータ
- next()メソッドを持つが、その戻り値はPromiseとなる
-
for-await-of
文で作る
-
- next()メソッドを持つが、その戻り値はPromiseとなる
メタプログラミングを学ぶ
- Proxy
-
arrayProxy = new Proxy(array, {})
-
arrayProxy
に対する操作はarray
に反映される-
array
そのままの挙動となる- ハンドラオブジェクトに
{}
ではなくメソッドを追加する- トラップと呼ばれる
- 決められた処理の中継に割り込める
- トラップと呼ばれる
- ハンドラオブジェクトに
-
-
- プロパティアクセスをプロキシする
get(), set(), has(), ownKeys()
-
array = [3.14, 9.8, 2.718]
arrayProxy = new Proxy(array, {
get(target, prop) {
return Math.round(target[prop]) // arrayProxy[0] が 3 となる
},
set(target, prop, value) {
if (!Number.isInteger(value)) {
throw new Error("not Integer")
}
target[prop] = value
},
has(target, prop) {
return prop < 2
},
ownKeys(target) {
return ["0", "1", "length"]
}
})
- 関数やコンストラクタの呼び出しをプロキシする
apply(), construct()
- 取り消し可能なProxyを作成する
- プロキシオブジェクトはターゲットの参照を保持しているためガベージコレクタに回収されない
-
Proxy.revocable()
で取り消す
-
- プロキシオブジェクトはターゲットの参照を保持しているためガベージコレクタに回収されない
Webを学ぶ
- Web
- HTML文章の集合からJSで繋がれたコンテンツの集合になっていった
- グローバルオブジェクト
- 宣言していない変数や定数
-
globalThis
オブジェクトのプロパティ-
globalThis === window
同じ
-
- console
- location
- navigator
-
- 宣言していない変数や定数
- ドキュメントオブジェクトモデル(DOM)
- DOMの構造
- HTML, XML, SVG などを表現する
- 木構造
- DOMツリー
-
childNodes[0]
で子ノードを辿っていける
-
- DOMツリー
- 主要オブジェクト
- 要素への操作
-
document.body.childNodes
- Nodeオブジェクトのプロパティ
-
Text
整形のための改行なども含む- 整形のための要素が必要になることはほとんどない
-
- Nodeオブジェクトのプロパティ
-
document.body.children
- Elementオブジェクトのプロパティ
- HTML要素しか含まない
- idを持つ子要素に直接アクセスできる
document.body.children.exampleId
- Elementオブジェクトのプロパティ
-
- 要素を検索する
getElementsByTagName()
getElementById()
getElementsByClassName()
querySelector()
querySelectorAll()
- 要素のコンテンツを操作する
-
textContent
- すべてのテキストを返す
-
innerText
- 実際に表示されているテキストだけを返す
-
- 要素を追加する
- 作る
createElement()
createNode()
- 追加する
appendChild()
insertBefore()
prepend()
append()
- 作る
- 要素を入れ替える
replaceChild()
- console上でそのまま編集する
document.body.contentEditable = true
- DOMの構造
- CSSオブジェクトモデル
-
document.styleSheets[0].cssRules
- すべてのルールを取得できる
-
setProperty()
で書き換えられる -
insertRule()
で挿入する
-
- イベント
- 「何かの出来事」が生じたら「何かの処理」を行う
- イベント処理
-
addEventListener()
とコールバック関数で実現する-
document.body.addEventListener("click", evt => {
-
-
- イベント処理
#${Math.floor(Math.random() * 0xffffff).toString(16)}
})```
-removeEventListener()
- 無名関数は削除できない
- 名前をつけて渡しておく必要がある
- `dispatchEvent()`
- 任意のタイミングでイベント発火させる- 代表的なイベント
-
keydown
- キーが押された時
-
keyup
- 押されたキーが解放された時
-
- イベントハンドラの探索順序
- HTMLタグにはデフォルトでイベントに反応するものがある
- 「何かの出来事」が生じたら「何かの処理」を行う
- Web Components
- 独自の機能や見た目のタグを作成できる
- Custom Elements
- HTMLElementを継承したクラスを作る
-
customElements.define()
で登録する
- Shadow DOM
- Shadow DOM 外の描画に影響を与えないDOMツリー
- 通常のDOMツリーに追加できる
- Shadow DOM 外の描画に影響を与えないDOMツリー
- HTML Template
-
<template>
タグ- 画面には描画されないがJSから参照できるDOM要素
-
<template>
とJSを組み合わせて実際のDOMに描画する- HTMLとJSを分離できる
- attribute を引数のようにコンテンツの中身に使うなど
- HTMLとJSを分離できる
-
- 画面には描画されないがJSから参照できるDOM要素
-
// あっという間にお絵かき帳
document.styleSheets[0].insertRule(`
.dot {
position: absolute;
width: 5px;
height: 5px;
background-color: black;
}
`)
let clicking
document.body.addEventListener("mouseup", () => clicking = false)
document.body.addEventListener("mousedown", () => clicking = true)
document.body.addEventListener("mousemove", evt => {
if(!(clicking && evt.shiftKey)) return
const dot = document.createElement("div")
dot.className = "dot"
dot.style.left = `${evt.clientX}px`
dot.style.top = `${evt.clientY}px`
document.body.append(dot)
})
ネットワークを学ぶ
- URI(Uniform Resource Identifier)
- 「求めるコンテンツを示す手段」
- 電話番号のようなもの
- どうやってコンテンツを受け渡すかはそのあとの話
-
https://www.amazon.co.jp/s?k=javascript&ref=nb_sb_noss_2
の構造- スキーム
https
- デリミタ
:
- オーソリティ
-
//amazon.com
- プレフィックス
//
- ホスト
amazon.com
- プレフィックス
-
- パス
/s
- クエリ
k=javascript&ref=nb_sb_noss_2
- スキーム
- 包含
- URI(Uniform Resource Locator)
- URN(Universal Resource Name)
-
encodeURI()
- そのままURIとして使える
-
encodeURIComponent()
- そのままURIとして使えないが、クエリパラメータとして使える
- 「求めるコンテンツを示す手段」
- HTTP
- 通信プロトコル
- 「もしもし〇〇ですが……」から始まる一連の儀礼や手順
- リクエスト・レスポンス型
- ステートレス
- 通信プロトコル
- WebAPI
- REST
- URIでリソースを一意に識別する
- GET, POST, PUT, PATCH, DELETE を使用する
- REST
- fetch
- 404エラーでも
then()
が呼び出される- then の中で status を確認する
if (!response.ok) throw new Error(response.statusText)
- then の中で status を確認する
- 404エラーでも
-
navigator.sendBeacon()
- ページナビゲーションに影響を与えずにビーコンを送信できる
- HTTP以外のプロトコル
- HTTP/2
- バイナリベース
- リクエスト・レスポンスの多重化ができる
- WebSocket
- 双方向にデータを送信できる
- WebRTC
- ブラウザ同士のリアルタイム通信ができる
- HTTP/2
ストレージを学ぶ
- Cookie
- DevToolsから確認する
- コンソールから確認する
- document.cookie
- HttpOnlyが設定されているとJSからはアクセスできない
- セッションIDをJSから読み込めるとセキュリティの問題になることがあるため
- 読取はまとめて得られるが代入は1エントリずつ
document.cookie = "power=E"
- 内部的なフィールドに値を設定し、それを文字列形式で読み出すゲッターとセッター
- HttpOnlyが設定されているとJSからはアクセスできない
- document.cookie
// JSでCookieを取得する
let cookieMap = () => new Map(document.cookie.split(/;\s*/).map(kv => {
const ms = kv.match(/([^=]+)=(.*)/)
return [ms[1], ms[2].replace(/(^"|"$)/g, "")]
}))
cookies = cookieMap()
cookies.get("lang")
// Cookieの大まかな内部構造
let doc = {
_cookie: new Map(),
get cookie() {
return [...this._cookie].map(kv => kv.join("=")).join(";")
},
set cookie(val) {
this._cookie.set(...val.split("="))
}
}
doc.cookie = "power=B"
doc.cookie = "spec=C"
doc.cookie // "power=B;spec=C"
// 属性を指定する
document.cookie = "power=B;max-age=1000"
- WebStorage
- サーバにデータが送信されない
- クライアント側でだけ利用できる
- Cookieは必ず送信されてしまう
- クライアント側でだけ利用できる
- 5~10MB程度のデータ
localStorage.getItem()
-
localStorage.setItem()
- 文字列以外はJSONで入れる
- 容量制限を超えるとエラーが出る
localStorage.removeItem()
-
localStorage.clear()
- すべてのデータをまとめて削除する
- サーバにデータが送信されない
- IndexedDB
- オブジェクト指向データベース
- 接続
-
indexedDB.open("jojodb", 1)
- 非同期で行われる
-
- オブジェクトストアを作成する
db.createObjectStore("satnds", {keyPath: "id", autoIncrement: true})
- インデックスを定義する
standStore.createIndex("nameIndex", "name", {unique:true})
- オブジェクトを追加する
-
db.transaction(["stands"], "readwrite)
- トランザクションを開始する
-
transaction.objectStore("stands")
- オブジェクトストアを取り出す
-
standStore.add()
- 追加する
- 非同期で実行される
- 結果は
IDBRequest
オブジェクト
- 結果は
- 非同期で実行される
- 追加する
-
- オブジェクトを取得する
standStore.get(1)
マルチメディアを学ぶ
- グラフィック系APIの操作
センサーとデバイスを学ぶ
- モバイルデバイスのセンサー取得法など
PWAを学ぶ
-
ServiceWorker
-
ネイティブアプリを超える
- URIでアプリケーションを共有できる
- Web Share API
- 支払い情報やログイン情報をブラウザでまとめられる
- PaymentRequest API
- URIでアプリケーションを共有できる
セキュリティを学ぶ
- サービスが家ならブラウザはサービスにつながるドアで、ログインは家の鍵
- ユーザーが誰か確認する
- 認証
- 機能の利用を許可する
- 認可
- ユーザーが誰か確認する
- JSが安全に利用できる理由
- サンドボックスで動作するから
- 同一オリジンポリシー
- オリジン
- スキームとホストとポート番号の組み合わせ
- オリジンが異なる時に制限されるもの
- fetch()
- Cookieの読み書き
- WebStorageやIndexedDBへのアクセス
- CanvasのgetImageData()
- CORS(Cross-Origin Resource Sharing)
- リクエストのOriginヘッダにオリジンを設定して送信する
- サーバはそのオリジンを確認する
- 通信許可ならAccess-Control-Allow-Originヘッダを設定したレスポンスを返す
- 一定期間クロスオリジンの通信が許可される
- 通信許可ならAccess-Control-Allow-Originヘッダを設定したレスポンスを返す
- サーバはそのオリジンを確認する
- リクエストのOriginヘッダにオリジンを設定して送信する
- オリジン
- ローカルファイルアクセス
- クリップボードアクセス
- 同一オリジンポリシー
- サンドボックスで動作するから
- 代表的な攻撃
- クロスサイトスクリプティング(XSS)
-
${name}
部分に<script>alert(document.cookie)</script>
などを入れられる- セッションIDの漏洩
- セッションハイジャック
- セッションIDの漏洩
- 対策
-
<
というようなHTMLエンティティに置換して埋め込む - Cookieの値を信用しない
- 重要情報はサーバ上に保存する
- Cookieは言語やスタイルの設定などにする
- セッションIDはCookieをHttpOnlyにしてJSから読み取れないようにする
-
-
- クロスサイトリクエストフォージェリ(CSRF)
- ログイン済みのユーザに攻撃サイトを表示させてiframeでパスワードリセットさせるなど
- 対策
- 本来の
<form>
タグからしかリクエストできないようにする-
<form>
に隠しパラメータとしてサーバで生成した乱数を設定する
-
- 本来の
- クロスサイトスクリプティング(XSS)
- Credential Management API
- JSからブラウザの「バスワードを保存」機能を利用できる
- JSを通じて得られるハードウェアに関する情報
- 意図的に不正確な値が返されることがある
- 情報を集めてユーザーを特定するフィンガープリンティングを避けるため
- 意図的に不正確な値が返されることがある
パフォーマンスを学ぶ
- 詳細な時間測定
- パフォーマンスを改善する
- Web Worker
worker1 = new Worker("js/worker1.js")
- やりとりできるデータ
- 関数オブジェクトとDOMノード以外
- 構造化クローンして受け渡されるから
- コピーが重すぎる
- Transferableオブジェクト
- 参照だけ受け渡す
- 高速になる
- 参照だけ受け渡す
- Transferableオブジェクト
- コピーが重すぎる
- 構造化クローンして受け渡されるから
- 関数オブジェクトとDOMノード以外
- WebAssembly
- Web Worker
学び続けるために
- ECMAScript
- 標準化までの5ステージ
- 0: 藁人形(Strawperson)
- 「こういう仕様を考えた」と宣言した状態
- 1: 提案(Proposal)
- 課題と解決策とAPIの概要、代表者が決まる
- デモなどで実際の動作を確認する
- 課題と解決策とAPIの概要、代表者が決まる
- 2: 草案(Draft)
- 議論が深まり正式なフォーマットで仕様がまとめられる
- 公式のフォーマットで正確に記述することが目的
- 議論が深まり正式なフォーマットで仕様がまとめられる
- 3: 候補(Candidate)
- 仕様書が完成して指名されたレビュアーとすべてのECMAScriptエディタが承認する
- 実際の利用からフィードバックを得て改善することが目的
- 仕様書が完成して指名されたレビュアーとすべてのECMAScriptエディタが承認する
- 4: 完了(Finished)
- 受け入れテストが作成される
- ECMA総会に提出されて批准されると標準化が完了となる
- 受け入れテストが作成される
- 0: 藁人形(Strawperson)
- 標準化までの5ステージ
- Web API
- World Wide Web Consortium(W3C)
- Web Incubator Community Group(WICG)
- Web Hypertext Application Technology Working Group(WHATWG)
- Living Standard
- Internet Engineering Task Force(IETF)
- Khronos Group