JavaScript
ブラウザの中で動く、いちばん近い言語
いま85本。実行して確かめたものだけを置いています。
01学ぶ
順番に積み上げる
✓array/basics
配列の基本 — 作る・取り出す・数える
配列は値を順番に並べて1つの名前で扱う入れ物です。作り方、番号での取り出し方、長さの数え方、範囲の外を読んだときに何が起きるかまでを、実行しながら確かめます。
✓array/loop
配列を繰り返す — for / for...of / forEach
配列の要素を1つずつ処理する3つの書き方を、違いが分かる形で比べます。途中で抜けられるか、添字が使えるか、非同期で待てるか。選ぶ基準まで実行して確かめます。
✓array/transform
配列を変換する・絞り込む — map と filter
ループで書いていた「新しい配列を作る」処理を map と filter に置き換えます。繋げて書く方法、元の配列が変わらないこと、途中で空になっても落ちない理由…
✓function/basics
関数の基本 — 作る・呼ぶ・返す
関数の3つの書き方と、それぞれで変わること。戻り値を書き忘れたときに何が返るか、アロー関数でオブジェクトを返すときの落とし穴までを、実行しながら確かめます。
✓function/higher-order
関数を値として扱う — 渡す・返す・包む
関数は値なので、変数に入れ、配列に並べ、引数として渡せます。map に渡している形の正体、関数を返す関数、既存の関数を包んで機能を足す形までを実行して確かめます…
✓function/scope
スコープと閉包 — 変数はどこから見えるか
変数が見える範囲と、関数が「作られた場所の変数を覚えている」という性質を扱います。ループの中で作った関数が全部同じ値になる有名な罠と、その原因までを実行して確か…
✓object/basics
オブジェクトの基本 — 作る・読む・書き換える
オブジェクトは名前を付けて値をまとめる入れ物です。作り方、ドットと角括弧の使い分け、無い鍵を読んだときの結果、あるかどうかの調べ方、同じものを指すという性質まで…
✓object/iterate
オブジェクトを回す・変換する
オブジェクトには map も filter もありません。entries() で配列にしてから配列のメソッドを使い、 fromEntries() で戻します。鍵…
✓object/nested
入れ子のオブジェクトを安全に扱う
深いところを辿ると途中で落ちます。オプショナルチェーンで落ちないようにする方法、分割代入で必要な値だけ取り出す書き方、既定値の付け方と ?? と || の違いを…
✓string/basics
文字列の基本 — 作る・つなぐ・数える
文字列の作り方、テンプレートリテラルでの組み立て、length での数え方、そして「一度作った文字列は書き換えられない」という性質までを、実行しながら確かめます…
✓string/search
文字列を探す・分ける・置き換える
includes() と indexOf() の使い分け、-1 が返る理由と 0 が falsy になる落とし穴、大文字小文字を無視した検索、split() と…
✓string/slice
文字列を切り出す・整える — slice と trim
slice() で必要な部分だけ取り出す方法と、substring() との違いを実行して比べます。 trim() で落とせる空白と落とせない空白、padSta…
✓string/unicode
文字を正しく数える — 絵文字と結合文字
length が見た目の文字数と合わない理由を、サロゲートペアと結合文字から説明します。スプレッド構文と Intl.Segmenter による数え方の違い、正規…
02逆引き
やりたいことから引く
✓array/chunk
配列を決まった数ずつに分ける
slice() を繰り返して塊にします。端数の扱い、空配列のとき、要素数より大きい数を渡したとき、そして 0 を渡すと止まらなくなる理由まで、実行して確かめます…
✓array/compare
2つの配列を比べる — 同じか、共通は何か
配列同士を === で比べても中身は見ません。中身が同じか調べる方法、順序を無視して比べる方法、共通・差分の求め方、オブジェクトの配列で気をつけることまで実行し…
✓array/flatten
入れ子の配列を平らにする
入れ子になった配列を1段階だけ、または全部平らにする方法をまとめます。flat() の深さ指定、 flatMap() で変換と平坦化を同時にやる書き方、穴が消え…
✓array/group
配列をキーごとにまとめる(グループ化)
Object.groupBy が使えるならそれが最短です。使えない環境向けの reduce での書き方、キーが数値や undefined になる罠、件数だけ数え…
✓array/insert-remove
配列の途中に入れる・途中から消す
splice() は元の配列を書き換え、消したものを返します。引数の意味、挿入と置き換え、ループの中で消すと1つ飛ばす理由、元を壊さない toSpliced()…
✓array/max-min
配列の最大値・最小値を求める
Math.max() にスプレッドで渡すのがいちばん短い書き方です。空配列で -Infinity になること、 null が 0 に化けること、件数が多いと落ち…
✓array/partition
配列を条件で2つに分ける
条件に合うものと合わないものを、1回のループで2つの配列に分けます。 filter() を2回書く方法との違い、条件の否定を書き間違えて件数が合わなくなる罠まで…
✓array/remove-duplicates
配列から重複を取り除く
配列の重複を消す最短の書き方は [...new Set(arr)] です。順序は保たれます。オブジェクトの配列では消えない理由と、その場合の書き方も載せています…
✓array/search
オブジェクトの配列から探す
1件なら find()、複数なら filter()、あるかどうかなら some()。大文字小文字や全角半角で見つからない理由、複数の項目をまたいで探す形、何度も…
✓array/sort-numbers
配列を数値の大きさで並び替える
sort() は既定で文字列として比べるため、数値を渡すと [1, 10, 2] のように並びます。比較関数の書き方、元の配列を壊さない方法、日本語やオブジェク…
✓array/sum
配列の合計を出す
合計は reduce に初期値 0 を渡すのが基本です。小数がずれる理由、空配列で例外になる条件、オブジェクトの配列の合計、大きすぎる数の扱いまで、実行して確か…
✓async/parallel
複数の非同期処理を同時に走らせる
await をループの中で書くと1つずつ順番に待ってしまいます。Promise.all で同時に走らせる書き方、1つ失敗したときの扱い、forEach で待てな…
✓async/retry
失敗したら再試行する
一時的な失敗だけをやり直します。回数で打ち切る書き方、待ち時間を伸ばす理由、やり直してはいけない失敗の見分け方、最後の失敗を握りつぶさない形までを実行して確かめ…
✓async/timeout
非同期処理に制限時間を付ける
Promise.race() で時間切れにできますが、遅いほうは裏で走り続けます。本当に止めるには AbortSignal が要ります。両方の書き方と、どちらを…
✓date/diff
2つの日付の差を日数で出す
引き算するとミリ秒が返ります。86400000 で割れば日数ですが、時刻が混ざると1日ずれます。日付だけに揃えてから引く形、負の差、月をまたぐ場合、年齢の数え方…
✓object/empty-check
空かどうかを調べる — 配列・オブジェクト・文字列
空の配列も空のオブジェクトも真なので、if (value) では判定できません。それぞれの正しい調べ方、null と空を分けるべき理由、1つの関数にまとめる形ま…
✓object/merge
オブジェクトを結合する
結合はスプレッド構文が最短です。ただしコピーされるのは1階層目だけで、入れ子は元と共有されます。undefined で上書きされる罠と、深く複製する方法までまと…
✓object/pick
オブジェクトから必要な鍵だけ取り出す・除く
entries() で配列にして絞り、fromEntries() で戻します。分割代入の残余で除く短い書き方、無い鍵を渡したとき、入れ子が共有されたままになる点…
✓string/format-date
日付を「2026-09-08」や「2026年9月8日」に整形する
日付を決まった形の文字列にする方法をまとめます。Intl.DateTimeFormat と toISOString の使い分け、時間帯で結果が変わる落とし穴、月…
✓string/to-number
文字列を数値に変換する
Number() と parseInt() と単項プラスは、失敗したときの振る舞いが違います。空文字・全角・単位つき・カンマ区切りで何が起きるかを実行して確かめ…
✓string/truncate
文字列を決まった文字数で切り詰める
長い文字列を指定した文字数で切って「…」を付ける方法をまとめます。slice() で絵文字が壊れる理由、スプレッド構文で足りない場面、Intl.Segmente…
✓url/query
URL のクエリ文字列を読む・組み立てる
自分で split() しないでください。URLSearchParams が符号化も復号も同じ値の複数指定も扱います。必ず文字列で返ること、空とキー無しの見分け…
03調べる
用語と仕様
✓array/every-some
every() と some() — 全部か、1つでもあるか
every() は全部が満たすか、some() は1つでも満たすかを true / false で返します。空配列で答えが逆になること、途中で止まること、inc…
✓array/filter
Array.prototype.filter()
filter() は配列の各要素を関数に通し、true になった要素だけを集めた新しい配列を返します。元の配列は変わりません。要素数は減ることがあります。
✓array/find
Array.prototype.find()
find() は条件に合う最初の要素を返します。見つからなければ undefined です。途中で止まること、空振りの扱い、findIndex や filter…
✓array/from
配列を作る — Array.from() / Array.of() / new Array()
new Array(3) が作るのは「穴が3つ」で、map() が動きません。Array.from() との違い、 fill() で同じオブジェクトが共有される…
✓array/includes
Array.prototype.includes() と some() / every()
値が入っているかを調べる includes、条件で調べる some と every の違いをまとめます。 NaN が見つかる理由、型が違うと一致しない話、空配列…
✓array/join
join() — 配列を1本の文字列にする
join() は要素を区切り文字で繋ぎます。null と undefined が空文字になること、区切りを省くとカンマになること、入れ子の配列が平らに見えること…
✓array/map
Array.prototype.map()
map() は配列の各要素を関数に通し、その戻り値を集めた新しい配列を返します。元の配列は変わりません。要素数も変わりません。
✓array/push
push() / pop() / shift() / unshift()
4つとも元の配列を書き換えます。それぞれの戻り値、空配列で何が返るか、配列を丸ごと足すと入れ子になる理由、元を変えずに同じことをする書き方までを実行して確かめま…
✓array/reduce
Array.prototype.reduce()
reduce() は配列を1つの値にまとめます。初期値を省いたときの落とし穴、空配列で例外になる条件、合計・グループ化の書き方、いつ使わないほうがよいかまでまと…
✓array/slice
Array.prototype.slice() と splice()
名前が似ている slice() と splice() は、まったく別のものです。取り出すだけか元を書き換えるか、引数の意味の違い、負の数の扱い、浅いコピーになる…
✓array/sort
Array.prototype.sort() と toSorted()
sort() は比較関数を渡さないと文字列として並べます。比較関数が返すべき値、真偽値を返すと並ばない理由、undefined と穴の位置、安定ソートの保証まで…
✓class/class
class — 作る・継承する・隠す
コンストラクタ、メソッド、getter、静的メンバ、継承、# で始まる非公開フィールドまでを扱います。 new を忘れると落ちる理由、JSON にすると非公開が…
✓collection/map-set
Map と Set
Map はどんな値でも鍵にでき、Set は重複を持ちません。オブジェクトや配列と何が違うのか、同じ値とみなす基準、JSON にできない理由、集合の演算までを実行…
✓date/date
Date — 作る・比べる・差を出す
Date が持っているのは 1970 年からのミリ秒だけです。比較が動く理由、差が引き算で出る理由、月を足すと 1/31 が 3/3 になる理由、壊れた日付の見…
✓error/error
Error と try / catch / finally / throw
Error が持っているもの、throw できるもの、finally が必ず動くこと、JSON にすると空になる理由、 cause で原因を繋ぐ書き方、独自のエ…
✓function/parameters
関数の引数 — 既定値・可変長・分割代入
既定値が働くのは undefined のときだけです。null では働きません。可変長引数の受け取り方、オブジェクトで受けて名前を付ける書き方、length が…
✓iterator/iterable
反復可能とイテレータ — for...of で回せるものの正体
for...of とスプレッドが使えるかどうかは Symbol.iterator を持つかで決まります。自分で作る方法、ジェネレータ、1度きりしか回せないこと、…
✓json/parse
JSON.parse() と JSON.stringify()
JSON との変換で何が消え、何が形を変えるのかをまとめます。undefined や Map が黙って落ちる理由、循環参照で例外になる条件、reviver と …
✓number/rounding
数値を丸める — Math.round / floor / ceil / trunc と toFixed
4つの丸め方の違い、負の数で結果が分かれる理由、toFixed が文字列を返すこと、そして 1.005 が 1.00 になる理由と、その回避策も効かない場面まで…
✓object/assign
Object.assign() と Object.freeze()
Object.assign() は第1引数を書き換えて返します。後ろが勝つこと、複製が1段しか効かないこと、 getter が値に変わること、freeze() …
✓object/keys
Object.keys() / values() / entries()
オブジェクトのキー・値・組を配列で取り出します。継承したものや列挙できないものは入りません。数字に見えるキーが先に来る理由、配列に戻す方法まで実行して確かめます…
✓operator/optional-chaining
?. と ?? — 無いかもしれない値を安全に読む
?. は null と undefined のときだけ止まります。?? は 0 や空文字を既定値で潰しません。連鎖が丸ごと止まること、?. が守ってくれない場面…
✓operator/spread
スプレッド構文と残余 — ... の2つの意味
同じ ... が、広げる側と集める側で逆の意味になります。配列・オブジェクト・関数それぞれの使い方、後ろ勝ちの上書き、複製が1段しか効かない点までを実行して確か…
✓promise/promise
Promise — then / catch / finally と async / await
Promise は「あとで決まる値」を表します。3つの状態、then の繋がり方、途中で投げたときの流れ、 async 関数が必ず Promise を返すこと、…
✓regexp/test-match
正規表現で探す — test() と match() と matchAll()
あるかどうかだけなら test()、取り出すなら match()、全部取り出すなら matchAll() です。 g フラグを付けたときに戻り値の形が変わること…
✓string/replace
String.prototype.replace() と replaceAll()
replace() は文字列を渡すと最初の1つしか置き換えません。全部置き換える書き方、 $ が特別扱いされる落とし穴、関数で置き換える方法までを実行して確かめ…
✓string/split
String.prototype.split()
split() は文字列を区切って配列にします。見つからないとき、空文字で分けたとき、絵文字が壊れる理由、連続した区切りの扱いまで、実行して確かめます。
✓string/template
テンプレートリテラル — 値を埋める・改行する・加工する
バッククォートで囲むと値を埋め込め、改行もそのまま書けます。何を入れても文字列になること、オブジェクトが [object Object] になること、タグ付きテ…
✓string/trim-pad
trim() / padStart() / padEnd() / repeat()
前後の空白を落とす trim()、桁を揃える padStart() / padEnd()、繰り返す repeat()。全角空白も落ちること、長すぎると詰めないこ…
✓timer/set-timeout
setTimeout() / setInterval() — 後で動かす
0 ミリ秒を指定しても、いま動いている処理が終わるまで動きません。止め方、引数の渡し方、 var で書いたループが全部同じ値になる理由、待つ関数の作り方まで実行…
04エラー
エラー文から引く
✓assignment-to-constant-variable
TypeError: Assignment to constant variable.
const で宣言した変数に代入し直すと出ます。const が固定するのは「値」ではなく「結びつき」で、配列やオブジェクトの中身は変えられます。その線引きと直し…
✓await-is-only-valid-in-async
SyntaxError: await is only valid in async functions
await を書ける場所は決まっています。async を付け忘れた関数、コールバックの中、昔の書き方のファイル。それぞれの直し方と、直った後に起きやすい間違いま…
✓cannot-access-before-initialization
ReferenceError: Cannot access 'x' before initialization
let / const / class を宣言より前で使うと出ます。var との違い、typeof でも避けられない理由、外側の同名変数を隠して起きる場合まで、…
✓cannot-convert-undefined-or-null
TypeError: Cannot convert undefined or null to object
Object.keys() などに null や undefined を渡すと出ます。落ちるものと黙って通るものの違い、値がそこで null になった原因の追い…
✓cannot-read-properties-of-undefined
TypeError: Cannot read properties of undefined (reading 'x')
undefined のプロパティを読もうとしたときに出ます。原因を多い順に並べ、それぞれ直したコードを載せています。スタックトレースのどこを見るかも書いています…
✓converting-circular-structure
TypeError: Converting circular structure to JSON
自分自身を辿れるオブジェクトを JSON.stringify() に渡すと出ます。親子の相互参照、 DOM 要素、通信のオブジェクト。どこで輪になっているかの見…
✓invalid-array-length
RangeError: Invalid array length
new Array() や length への代入に、負の数・小数・NaN・大きすぎる数を渡すと出ます。許される範囲、new Array(3) と Array.…
✓is-not-a-function
TypeError: x is not a function
関数でないものを呼んだときに出ます。綴り違い、配列でない値、this の外れ、読み込み方の食い違いなど、原因を多い順に並べ、それぞれ直したコードを載せています。
✓is-not-defined
ReferenceError: x is not defined
宣言していない名前を読もうとしたときに出ます。綴り違い、読み込み順、スコープの外、 Node とブラウザで存在しないもの。原因を多い順に並べ、それぞれ直したコー…
✓is-not-iterable
TypeError: x is not iterable
for...of やスプレッドや分割代入に、回せないものを渡したときに出ます。素のオブジェクト、null、通信の結果。原因を多い順に並べ、それぞれ直したコードを…
✓maximum-call-stack
RangeError: Maximum call stack size exceeded
関数の呼び出しが深くなりすぎたときに出ます。ほとんどは終わらない再帰です。止まる条件の書き忘れ、相互に呼び合う形、大きな配列の展開まで、原因別に直し方をまとめま…
✓unexpected-end-of-json
SyntaxError: Unexpected end of JSON input
JSON.parse に渡した文字列が途中で終わっているときに出ます。空の応答、204、途中で切れた本文、二重に読んだ本文。原因を多い順に並べ、落ちない受け取り…
✓unexpected-token
SyntaxError: Unexpected token
構文として読めなかったときに出ます。エラーの位置は壊れた場所ではなく気づいた場所です。 JSON.parse で出る場合が特に多く、その見分け方と直し方までまと…
05なぜ
仕組みの理由
✓float-precision
なぜ 0.1 + 0.2 は 0.30000000000000004 になるのか
2進数では 0.1 を正確に表せないためです。JavaScript 固有の問題ではありません。どこまで正確なのか、安全な比べ方、お金の扱い方までを実行して確かめ…
✓nan-equality
なぜ NaN === NaN は false なのか
NaN は特定の値ではなく「数値として表せなかった」という印です。そのため === では等しくなりません。includes や Set では等しく扱われる理由も…
✓semicolon-asi
なぜセミコロンを省いても動くのに、たまに壊れるのか
処理系が改行のところにセミコロンを補っています。ただし補わない場合があり、そこだけ意味が変わります。return の後の改行、行頭の括弧。実際に壊して確かめます…
✓strict-equality
なぜ == ではなく === を使うのか
== は型を揃えてから比べるため、0 == '' が true になるなど直感と外れます。推移律が成り立たない具体例、== を使ってよい唯一の場面、Object…
✓this-binding
なぜ this は呼び方で変わるのか
this は書いた場所ではなく、呼ばれ方で決まります。メソッドから取り出すと外れる理由、 strict モードでの違い、アロー関数だけが例外である仕組みを、実行…
✓typeof-null
なぜ typeof null は "object" なのか
仕様がそう定めているからです。理由は仕様に書かれていません。null を見分ける正しい方法、 undefined との使い分け、Object.prototype…
✓zero-index
なぜ配列の番号は0から始まるのか
先頭からの距離を番号にしているからです。0 始まりだと slice の範囲、長さの計算、ループの条件がすべて足し算・引き算だけで揃います。1 始まりで書いたとき…