node -v
, npm -v
でバージョン確認)。node myfile.js
)。git init
, git status
, git add <file>
, git commit -m "message"
, git log
, git diff
。git branch <branch-name>
, git checkout <branch-name>
(例: feature/login-form
)。「ログインフォームを作るぞ!という時に、本流から分岐して専用の作業スペースを作るイメージです。失敗しても本流は安全!」git remote add origin <url>
, git push -u origin main
。console.log()
: 「最も身近な探偵道具。」変数の値確認、処理の通過点確認。console.table()
: 配列やオブジェクトを見やすく表示するテクニック。const users = [{name: "Alice", age: 30}, {name: "Bob", age: 25}]; console.table(users);
ReferenceError: myFunction is not defined
→ 「myFunction
という名前のものがどこにも見つからないよ、というエラーです。関数名や変数名のタイプミス、または定義する前に呼び出そうとしていないか確認しましょう。」<script src="app.js"></script>
(外部ファイル)、<script>/* ここにコード */</script>
(インライン)。高階関数もどき:
// filepath: (第1章の説明箇所)
function operateOnArray(array, operation) {
const result = [];
for (let i = 0; i < array.length; i++) {
result.push(operation(array[i]));
}
return result;
}
const numbers = [1, 2, 3];
const doubled = operateOnArray(numbers, function(num) { return num * 2; }); // [2, 4, 6]
「operation
に渡す関数を変えるだけで、配列に対する処理内容を自由に変えられるのが面白いところです。」
Hello, World!
: コンソール (console.log("Hello, World!");
) とブラウザ表示 (alert("Hello, World!");
またはDOM操作で)。
HTML連携例:
// filepath: (第1章のHTML連携例)
<!DOCTYPE html>
<html>
<head><title>JS Test</title></head>
<body>
<p id="message">こんにちは</p>
<button onclick="changeMessage()">メッセージ変更</button>
<script>
function changeMessage() {
document.getElementById('message').textContent = 'JavaScriptで変更しました!';
}
</script>
</body>
</html>
コメント: // 一行コメント
, /* 複数行コメント */
。
セミコロン: ASI (Automatic Semicolon Insertion) の挙動と注意点。
ASIバグ例:
// filepath: (第1章の説明箇所)
function getObject() {
return // ASIによりここでセミコロンが挿入される
{
name: "ASI Trap"
}
}
console.log(getObject()); // undefined になる!
「ASIは便利な反面、意図しない挙動も。チームのスタイルガイドに従うのが賢明です。」
波括弧 {}
: ブロックを示す、オブジェクトリテラルで使う。
var
: 歴史的経緯と問題点(関数スコープ、巻き上げ)。基本的に使わない。let
: 再代入可能な変数を宣言(ブロックスコープ)。const
: 再代入不可能な変数を宣言(ブロックスコープ)。基本的にこちらを推奨。const user = {name: 'Alice'}; user.name = 'Bob';
はOK(箱の中身は変えられる)。でも user = {name: 'Charlie'};
はNG(箱自体を別のものに入れ替えるのはダメ)。変数が指し示すメモリアドレスが固定される。」図解推奨。string
(文字列): 'hello'
, "world"
, `template literal`
number
(数値): 123
, 3.14
, NaN
, Infinity
boolean
(真偽値): true
, false
null
: 「意図的に値がないことを示す」特別な値。document.getElementById('存在しないID')
)」「開発者が意図的に『値がない』ことを示すために代入する場合」。undefined
: 「値がまだ代入されていない」状態。symbol
: (ES6+) 一意で不変な値。オブジェクトプロパティのキーとして衝突を避ける。const RED = Symbol('赤');
列挙型のような使い方、Symbol.iterator
など既知のシンボル。bigint
: (ES2020+) Number
で表現できない大きな整数。金融計算、暗号処理など。123n
。typeof
演算子: typeof 123
→ "number"
。typeof null
→ "object"
(歴史的経緯)。typeof []
→ "object"
。var
で宣言された変数)。{}
ブロック内でのみ有効 (let
, const
で宣言された変数)。var
: 宣言のみがスコープの先頭に巻き上げられる(初期値はundefined
)。let
/const
: 宣言は巻き上げられるが、初期化されるまではTDZ (Temporal Dead Zone) にありアクセス不可(ReferenceError
)。console.log(a); var a = 1;
(undefined) vs console.log(b); let b = 1;
(Error)。String()
, Number()
, Boolean()
, parseInt()
, parseFloat()
。+
, ==
など) によって自動的に行われる変換。1 + "2"
→ "12"
, '5' - 1
→ 4
。true + false
→ 1
, [] + {}
→ "[object Object]"
。+
, -
, *
, /
, %
(剰余), **
(べき乗), ++
(インクリメント), --
(デクリメント)。==
(等価), ===
(厳密等価), !=
(不等価), !==
(厳密不等価), >
, <
, >=
, <=
。===
と !==
の使用を強く推奨。&&
(論理AND), ||
(論理OR), !
(論理NOT)。const name = user && user.profile && user.profile.name;
, const displayName = preferredName || defaultName || 'Guest';
=
, +=
, -=
, *=
, /=
, %=
, **=
.条件 ? trueの場合の値 : falseの場合の値
。()
を使って計算順序を明示するのが安全で読みやすいコードのコツです。」MDNへのリンク。Array
): 順序付けられた値のリスト。const arr = [1, "apple", true];
, new Array()
.arr[0]
。arr.length
。push()
: 末尾に追加 (破壊的、新しい長さを返す)。pop()
: 末尾を削除 (破壊的、削除した要素を返す)。shift()
: 先頭を削除 (破壊的、削除した要素を返す)。unshift()
: 先頭に追加 (破壊的、新しい長さを返す)。slice(start, end)
: 部分配列を返す (非破壊的)。splice(start, deleteCount, ...items)
: 要素を置換/削除/追加 (破壊的、削除した要素の配列を返す)。Object
): 名前付きプロパティの集まり。const obj = { key1: "value1", "two words": 2 };
, new Object()
.obj.key1
(キーが有効な識別子の場合)。obj["two words"]
。const prop = "key1"; obj[prop]
)、スペースやハイフンを含む、数値で始まる場合。動的プロパティ名 (obj['prop' + i] = val;
)。obj.newKey = "newValue";
, obj.key1 = "updatedValue";
.delete obj.key1;
.in
演算子とhasOwnProperty
:'key1' in obj
: プロトタイプチェーンも辿って存在確認。obj.hasOwnProperty('key1')
: オブジェクト自身のプロパティか確認。{} === {}
は false
(参照の比較)。プリミティブ型との違い。プロパティに関数を格納することで、オブジェクトが「振る舞い」を持つ。
例:
// filepath: (第3章の説明箇所)
let user = {
name: "高専太郎",
greet: function() {
// 「this」については、ここでは「このオブジェクト自身」くらいの簡単な説明に留める
console.log("こんにちは、" + this.name + "さん!");
}
};
user.greet(); // メソッド呼び出し
「このthis.name
のthis
は、今まさにgreet
メソッドを呼び出しているuser
オブジェクト自身のことを指しています。まるで、メソッドが『ご主人様!』と呼びかけているようなイメージですね。ただし、このthis
は時々気まぐれで、違うご主人様を指してしまうこともあるので、そのお話はまた後でじっくりと。」
console.log()
も console
オブジェクトの log
メソッド。
name
, age
プロパティと greet
メソッドを持つ。addSkill(skillName)
メソッドを追加し、skills
配列プロパティにスキルを追加。introduceSkills()
メソッドを追加し、スキルを列挙して自己紹介。setAge(newAge)
メソッドを追加し、年齢を更新。条件分岐:
if...else if...else
文。
switch
文:
case
と break
。break
を忘れるとフォールスルーする点に注意。
意図的なフォールスルーの例:
// filepath: (第4章の説明箇所)
let message = '';
const rank = 'gold';
switch (rank) {
case 'platinum': message += 'プラチナ特典利用可能。'; // breakなし
case 'gold': message += 'ゴールド特典利用可能。'; // breakなし
case 'silver': message += 'シルバー特典利用可能。'; break;
default: message = '通常会員特典のみ利用可能。';
}
// rankが'gold'なら "ゴールド特典利用可能。シルバー特典利用可能。"
三項演算子 (条件演算子): 条件 ? trueの場合の値 : falseの場合の値
。
注意点: 可読性が低下する場合があるので、複雑な条件分岐には if...else
を使用。
繰り返し処理 (ループ): フローチャートのような視覚的表現も活用。
for
ループ: for (初期化; 条件; 更新) { ... }
。while
ループ: while (条件) { ... }
。do...while
ループ: do { ... } while (条件);
(最低1回は実行)。while(true){}
の例(コメントアウト推奨)。Node.jsならCtrl+C
、ブラウザならタスクマネージャーで強制終了。ループの制御:
break
: ループを完全に抜ける。continue
: 現在の反復処理をスキップし、次の反復へ進む。コレクションとループ:
for...in
ループ: オブジェクトのプロパティを列挙。
配列には非推奨: プロトタイプチェーン上のプロパティも列挙する可能性、順序保証なし。
失敗例:
// filepath: (第4章の説明箇所)
Array.prototype.customProperty = "これは罠だ!";
const arr = [10, 20, 30];
for (const i in arr) { // i は文字列の "0", "1", "2", "customProperty"
if (arr.hasOwnProperty(i)) { // 自衛策
console.log(`Index: ${i}, Value: ${arr[i]}`);
}
}
delete Array.prototype.customProperty;
for...of
ループ (ES6+): イテラブルオブジェクト (配列、文字列、Map, Setなど) の要素を列挙。
for (const char of "こんにちは") { console.log(char); }
(サロゲートペアも正しく扱える)。演習例: FizzBuzz問題、配列要素の合計計算など。
function myFunction(param1, param2) { /*処理*/ return result; }
const myFunction = function(param1, param2) { /*処理*/ return result; };
const myFunction = (param1, param2) => { /*処理*/ return result; };
const myFunction = (param1, param2) => result;
(暗黙のreturn)const createObj = () => ({ key: 'value' });
(オブジェクトリテラルを返す場合)return
)。function greet(name = "Guest") { ... }
function sum(...numbers) { return numbers.reduce((acc, num) => acc + num, 0); }
this
の挙動: レキシカルthis
(アロー関数) vs 呼び出し方で決まるthis
(従来関数)。arguments
オブジェクト: アロー関数は持たない (レストパラメータで代替)。new
演算子: アロー関数はコンストラクタになれない。prototype
プロパティ: アロー関数は持たない。導入: 「実は、今まで使ってきた関数も、JavaScriptの世界では『オブジェクト』の一種なんだ。」
関数もプロパティを持てる:
// filepath: (第5章の説明箇所)
function calculateArea(width, height) {
if (calculateArea.callCount === undefined) calculateArea.callCount = 0;
calculateArea.callCount++;
return width * height;
}
calculateArea.description = "長方形の面積を計算する関数です。";
console.log(calculateArea(10,5), calculateArea.description, calculateArea.callCount);
関数は変数に代入できる (第一級オブジェクトの再確認)。
関数を他の関数の引数に渡せる (コールバック関数の基礎)。
関数を他の関数の戻り値にできる (クロージャの基礎)。
typeof
演算子の挙動: typeof myFunction
が "function"
を返すのは、それが「呼び出し可能なオブジェクト」だから。「内部的に[[Call]]という特別な仕組みを持っている、とだけ覚えておけばOKです。」
グローバルスコープ、関数スコープ、ブロックスコープ。
レキシカルスコープ (静的スコープ): 関数が定義された場所でスコープが決まる。
// filepath: (第5章の説明箇所)
let x = "global_x"; let y = "global_y";
function outerFunc() {
let x = "outer_x";
function innerFunc() {
let x = "inner_x";
console.log("innerFunc sees x as: " + x); // inner_x
console.log("innerFunc sees y as: " + y); // global_y
}
return innerFunc;
}
const myInnerFunc = outerFunc(); myInnerFunc();
「関数innerFunc
は、それが定義された場所(outerFunc
の中)の『空気』(スコープ)を覚えています。」
(function() { ... })();
try...catch...finally
構文:
try
: エラーが発生する可能性のあるコード。
catch (error)
: エラー発生時の処理。error
オブジェクト (error.name
, error.message
)。
finally
: 成功/失敗に関わらず必ず実行される処理 (リソース解放など)。
// filepath: (第5章の説明箇所)
let resourceBusy = false;
try {
resourceBusy = true; /* リソース使用開始 */
// if (Math.random() < 0.5) throw new Error("処理中に問題発生!");
} catch (e) {
console.error("エラー: " + e.message);
} finally {
resourceBusy = false; /* リソース解放 */
console.log("リソース解放完了。busy: " + resourceBusy);
}
throw new Error('メッセージ')
: 意図的にエラーを発生させる。
エラーオブジェクトの種類: Error
(汎用), TypeError
(型不正), SyntaxError
(文法ミス), ReferenceError
(未定義変数参照), RangeError
(数値範囲外), URIError
(URI関連)。それぞれが発生する短いコード例。
DOM (Document Object Model) とは:
document
オブジェクト: DOMツリーの入り口。document.title
, document.URL
など。DOM要素の取得:
document.getElementById('id')
: 特定のIDを持つ要素 (単一)。document.getElementsByTagName('tag')
: 指定タグ名の要素群 (HTMLCollection
- ライブ)。document.getElementsByClassName('class')
: 指定クラス名の要素群 (HTMLCollection
- ライブ)。document.querySelector('selector')
: CSSセレクタに一致する最初の要素 (単一 - 静的)。document.querySelectorAll('selector')
: CSSセレクタに一致する全要素 (NodeList
- 静的)。HTMLCollection
(ライブ): DOMの変更が即座に反映される。
NodeList
(静的、querySelectorAll
の場合): 取得時点のスナップショット。
問題点: ループ中にDOM変更を行う場合、ライブコレクションはインデックスずれや無限ループの危険性。
// filepath: (第6章の説明箇所)
// ライブコレクションの問題例
const listItemsLive = document.getElementsByTagName('li');
for (let i = 0; i < listItemsLive.length; i++) { /* 削除するとlengthが変わり問題発生しうる */ }
// 静的コレクションなら安全
const listItemsStatic = document.querySelectorAll('li');
listItemsStatic.forEach(item => { /* item.remove() */ });
判断基準: 「常に最新のDOM状態を反映させたい場合はライブ、ループ処理などで安全に扱いたい場合は静的(またはArray.from()
で配列化)が良いでしょう。」
ノードの種類: 要素ノード、テキストノード、コメントノードなど。
element.childNodes
(テキストノード等も含むNodeList) vs element.children
(要素ノードのみのHTMLCollection)。DOM要素の内容変更:
element.textContent
: テキスト内容のみ (安全、推奨)。element.innerHTML
: HTML構造を含む内容 (XSSリスクあり)。XSSデモ:
// filepath: (第6章のHTML連携例)
<div id="target"></div> <input id="userInput">
<button onclick="document.getElementById('target').innerHTML = document.getElementById('userInput').value;">innerHTML更新</button>
<button onclick="document.getElementById('target').textContent = document.getElementById('userInput').value;">textContent更新</button>
<!-- userInputに <img src="x" onerror="alert('XSS!')"> と入力 -->
「ユーザー入力内容をinnerHTML
に使うのは危険。原則textContent
を。」
DOM要素の属性操作:
element.getAttribute('attrName')
element.setAttribute('attrName', 'value')
element.removeAttribute('attrName')
data-*
): element.dataset.customName
(HTML: data-custom-name
)。JavaScriptからHTML要素に追加情報を紐付ける。DOM要素のスタイル操作:
element.style.property
: element.style.color = 'red';
(インラインスタイル)。element.classList
: add()
, remove()
, toggle()
, contains()
。toggle
実践例: ダークモード切り替え。
// filepath: (第6章のスクリプト箇所)
const toggleBtn = document.getElementById('darkModeToggle');
if (toggleBtn) toggleBtn.addEventListener('click', () => document.body.classList.toggle('dark-mode'));
DOM要素の動的変更:
document.createElement('tagName')
parentElement.appendChild(newChild)
, parentElement.insertBefore(newNode, referenceNode)
(referenceNode
がnull
ならappendChild
と同じ)。parentElement.replaceChild(newChild, oldChild)
childElement.remove()
(モダン), parentElement.removeChild(childElement)
(旧)。element.cloneNode(deep)
(deep=true
で子孫もコピー、false
なら自身のみ。イベントリスナーはコピーされない)。DOM操作のパフォーマンス:
display: none
の活用。要素のサイズや位置の取得: offsetWidth
, offsetHeight
, getBoundingClientRect()
(ビューポート相対位置と寸法)。
演習例: 「ボタンクリックで新しいリストアイテムが追加・削除される」機能の実装。
イベントとは: クリック、キー入力、マウス操作、ページの読み込み完了など。
click
, dblclick
, mousedown
, mouseup
, mousemove
, mouseover
/mouseout
(バブリングあり), mouseenter
/mouseleave
(バブリングなし)。keydown
, keyup
(keypress
は非推奨)。event.key
, event.code
の違い。submit
(フォーム送信時), change
(入力内容変更完了時), input
(入力内容変更中)。load
(全リソース読込完了), DOMContentLoaded
(DOM構築完了), resize
, scroll
。イベントリスナーの登録と解除:
element.addEventListener('eventName', callbackFunction, options)
: 推奨。options
: { capture?: boolean, once?: boolean, passive?: boolean }
element.removeEventListener('eventName', callbackFunction, options)
: メモリリーク防止に重要。登録時と同じ参照の関数が必要。on<event>
属性, element.onevent = handler
) は非推奨。イベントオブジェクト (event
): イベント発生時の情報を持つ。
event.target
: 実際にイベントが発生した要素。
event.currentTarget
: イベントリスナーが登録された要素。
違いの具体例:
// filepath: (第7章のHTML連携例)
<ul id="parent-list"><li>アイテム 1 <button>削除</button></li></ul>
<script>
// filepath: (第7章のスクリプト箇所)
document.getElementById('parent-list').addEventListener('click', function(event) {
console.log('currentTarget:', event.currentTarget); // <ul>
console.log('target:', event.target); // <li> or <button>
});
</script>
event.preventDefault()
: デフォルト動作をキャンセル (例: <a>
タグの画面遷移、フォームの送信)。
event.stopPropagation()
: イベントの伝播を止める。
イベント伝播:
addEventListener
の第3引数 { capture: true }
でキャプチャリングフェーズで補足。イベントデリゲーション: 親要素にイベントリスナーを一つ登録し、event.target
で処理を振り分ける。
メリット: 動的に追加される要素にも対応、リスナー数の削減。
具体例 (TODOリストの削除ボタン):
// filepath: (第7章のスクリプト箇所)
todoListElement.addEventListener('click', function(event) {
if (event.target.classList.contains('delete-button')) {
event.target.closest('li').remove();
}
});
イベントリスナー内での this
:
通常の関数: this
は event.currentTarget
(イベントリスナーが登録された要素) を指す。
アロー関数: this
は外側のレキシカルスコープの this
を維持する。
// filepath: (第7章のスクリプト箇所)
myButton.addEventListener('click', function() { console.log(this); /* myButton */ });
const obj = { method: function() { myButton.addEventListener('click', () => console.log(this)); /* obj */ }};
カスタムイベント: new CustomEvent('eventName', { detail: data })
と element.dispatchEvent(event)
。コンポーネント間の疎結合な連携。
イベントの頻度制御 (発展): scroll
, mousemove
など頻発イベントのパフォーマンス対策。
debounce
: 一定時間イベントが来なければ実行。throttle
: 一定時間ごとに一度だけ実行。 (概念紹介、実装は発展課題)localStorage
: オリジン単位、永続的(ブラウザを閉じても残る)。sessionStorage
: オリジン単位かつタブ/ウィンドウ単位、セッション中のみ(タブ/ウィンドウを閉じると消える)。setItem(key, value)
, getItem(key)
, removeItem(key)
, clear()
, length
, key(index)
。文字列のみ保存可能: JSON.stringify()
/ JSON.parse()
でオブジェクトを保存・復元。
// filepath: (第8章の説明箇所)
const settings = { theme: 'dark' };
localStorage.setItem('settings', JSON.stringify(settings));
const loaded = JSON.parse(localStorage.getItem('settings'));
保存容量制限 (通常5MB程度)。
同期API: 大量データの読み書きはUI応答性を損なう可能性。
Storage
イベント: localStorage
/sessionStorage
が別タブ/ウィンドウで変更された際に発火 (window.addEventListener('storage', callback)
)。タブ間通信。Expires
/Max-Age
: 有効期限。Domain
/Path
: 送信範囲。Secure
: HTTPS通信時のみ送信。HttpOnly
: JavaScriptからのアクセス禁止 (XSS対策)。SameSite
(Strict
, Lax
, None
): CSRF対策。None
の場合はSecure
必須。document.cookie
(煩雑)。Set-Cookie
ヘッダーで設定。クライアントでの複雑な操作はライブラリ検討。」JavaScriptはシングルスレッド:
非同期処理とは? なぜ必要か?:
ブロッキングを防ぎ、応答性の高いUIを実現するため。
UIブロッキング例:
// filepath: (第9章のスクリプト箇所)
// blockingButtonクリックで5秒間UIが固まる処理
// nonBlockingButtonクリックでsetTimeoutを使い5秒後に処理完了、UIは固まらない
「ブロッキング処理ボタンを押すと、5秒間は他の操作ができなくなるのを体験してみましょう。」
イベントループの構成要素と動作メカニズム:
setTimeout
, DOMイベント, fetch
などの非同期処理を実行する部分。JavaScriptエンジン外。setTimeout(fn, 0)
の挙動:
console.log('A'); setTimeout(() => console.log('B'), 0); console.log('C');
の出力順序予想 (A, C, B)。マイクロタスク vs マクロタスク:
マイクロタスク (Promise.then
, queueMicrotask
など) は、現在のマクロタスク完了後、次のマクロタスクの前にまとめて処理される。
具体例:
// filepath: (第9章のスクリプト箇所)
console.log('1: Script Start');
setTimeout(() => console.log('2: setTimeout (macro)'), 0);
Promise.resolve().then(() => console.log('3: Promise (micro 1)'))
.then(() => console.log('4: Promise (micro 2)'));
console.log('5: Script End');
// 出力順: 1, 5, 3, 4, 2
レンダリングとの関連: イベントループはブラウザのレンダリング処理とも関連。重い同期処理はレンダリングもブロックするが、非同期処理の合間にレンダリングが行われる。
伝統的な非同期処理: コールバック関数 (再訪):
setTimeout
やイベントハンドラでの利用。
コールバック地獄 (Pyramid of Doom): ネストが深くなり可読性・保守性が低下する問題。
// filepath: (第10章の説明箇所 - コールバック地獄の例)
// asyncOperation1((err1, res1) => { asyncOperation2(res1, (err2, res2) => { ... }) });
Promise: 非同期処理の最終的な結果を表すオブジェクト。
状態: pending
(待機中), fulfilled
(成功), rejected
(失敗)。一度状態が決まると変化しない。
Promiseコンストラクタ: new Promise((resolve, reject) => { /* 非同期処理 */ if (success) resolve(value); else reject(error); })
resolve(value)
: 成功を通知し、値を渡す。reject(error)
: 失敗を通知し、エラーオブジェクトを渡す。インスタンスメソッド:
.then(onFulfilled, onRejected)
: 成功時/失敗時のコールバックを登録。Promiseを返すためチェーン可能。.catch(onRejected)
: 失敗時のコールバックのみ登録 (.then(null, onRejected)
の糖衣構文)。.finally(onFinally)
: 成功/失敗に関わらず実行されるコールバック。Promiseチェーン: コールバック地獄の解消。
// filepath: (第10章の説明箇所 - Promiseチェーンの例)
// promiseOperation1().then(res1 => promiseOperation2(res1)).then(res2 => ...).catch(err => ...);
静的メソッド:
Promise.resolve(value)
: 即座に成功するPromiseを生成。Promise.reject(error)
: 即座に失敗するPromiseを生成。Promise.all(iterable)
: 全てのPromiseが成功したら成功。一つでも失敗したら失敗。並列処理。Promise.race(iterable)
: 最初に成功または失敗したPromiseの結果を採用。タイムアウト処理など。Promise.allSettled(iterable)
(ES2020): 全てのPromiseの結果(成功/失敗問わず)を配列で取得。Promise.any(iterable)
(ES2021): 最初に成功したPromiseの結果を採用。全て失敗したらAggregateError
で失敗。Async/Await (ES2017): Promiseを同期処理のように書ける糖衣構文。
async
関数: 関数宣言の前にasync
を付けると、自動的にPromiseを返す関数になる。
await
演算子: async
関数内でのみ使用可能。Promiseが解決されるまで処理を一時停止し、解決された値を返す。
エラーハンドリング: try...catch
構文を使用。
// filepath: (第10章の説明箇所 - Async/Awaitの例)
async function fetchData() {
try {
const response = await fetch('url');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('エラー:', error);
}
}
演習: Promiseチェーンで書いた処理をAsync/Awaitでリファクタリング。
エラーハンドリングの深掘り: Promiseチェーンでのエラー伝播、async/await
での複数await
に対するtry...catch
の範囲。
Fetch API: ブラウザ標準のHTTPリクエストAPI。Promiseベース。
fetch(url, options)
url
: リクエスト先のURL。options
(オブジェクト):method
: 'GET'
(デフォルト), 'POST'
, 'PUT'
, 'DELETE'
など。headers
: {'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN'}
など。body
: リクエストボディ。POST
などで使用。JSON.stringify({key: 'value'})
。mode
: 'cors'
(デフォルト), 'no-cors'
, 'same-origin'
。credentials
: 'include'
(Cookie送信), 'same-origin'
, 'omit'
(デフォルト)。Response
):response.ok
: HTTPステータスが200-299ならtrue
。response.status
: HTTPステータスコード (例: 200, 404)。response.statusText
: ステータスメッセージ (例: "OK", "Not Found")。response.headers
: Headersオブジェクト。response.headers.get('Content-Type')
などでヘッダー値取得。response.json()
: JSONとしてパース。response.text()
: テキストとして取得。response.blob()
: Blobオブジェクトとして取得 (画像など)。response.formData()
: FormDataとして取得。response.arrayBuffer()
: ArrayBufferとして取得。Fetch APIにおけるエラーハンドリング:
ネットワークエラー: fetch()
自体が失敗する場合 (例: DNS解決不可、オフライン)。Promiseがreject
され、.catch()
で捕捉。
HTTPエラーステータス: 4xx, 5xxエラー。fetch()
のPromiseはこれらではreject
されない。response.ok
やresponse.status
で判定が必要。
// filepath: (第11章のスクリプト箇所)
fetch('api/data')
.then(response => {
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
return response.json();
})
.then(data => console.log(data))
.catch(error => console.error('Fetchエラー:', error.message));
データの扱い: JSON (JavaScript Object Notation):
JSON.parse(jsonString)
: JSON文字列をJavaScriptオブジェクト/配列に変換。
JSON.stringify(jsObject)
: JavaScriptオブジェクト/配列をJSON文字列に変換。
演習: ネストしたJSONデータから特定情報を取り出す。
// filepath: (第11章の演習用JSONデータ例)
{ "user": { "name": "高専花子", "hobbies": ["プログラミング", "読書"] } }
「ユーザーの最初の趣味を取り出してください。」
CORS (Cross-Origin Resource Sharing):
http-server
のCORS有効化オプション (一時的)。本番はサーバー側で適切なCORSヘッダー設定が必要。リクエストのキャンセル: AbortController
とAbortSignal
を使用。
// filepath: (第11章のスクリプト箇所)
const controller = new AbortController();
const signal = controller.signal;
fetch('url', { signal })
.then(res => {/* ... */})
.catch(err => { if (err.name === 'AbortError') console.log('Fetch aborted'); });
// controller.abort(); // リクエストをキャンセル
ストリーミング (概要): response.body
(ReadableStream) を使った大きなデータの段階的処理。
セキュリティ (CSRFとCORS): CORSはオリジン間リソース共有、CSRFは別種の脆弱性。Fetch API利用時もサーバー側CSRF対策(トークンなど)が重要。
(参考) XMLHttpRequest
(旧), axios
(人気ライブラリ):
演習: 公開API (天気情報、国情報など) からデータを取得し、ウェブページに表示。
let
と const
(再確認): ブロックスコープ、再代入の可否。
アロー関数 (再確認): 構文、this
の挙動、arguments
非保持。
テンプレートリテラル: `Hello, ${name}!`
文字列埋め込み、複数行文字列、式埋め込み。
タグ付きテンプレートリテラル:
// filepath: (第12章の説明箇所)
function sanitize(strings, ...values) { /* ...エスケープ処理... */ return result; }
const html = sanitize`<div>${untrustedInput}</div>`;
デフォルトパラメータ(再確認): function greet(name = "Guest") {}
レストパラメータ(再確認): function sum(...numbers) {}
スプレッド構文: ...arrayOrObject
const newArr = [...oldArr, newItem];
const newObj = { ...oldObj, newProp: val };
Math.max(...numbersArray);
デストラクチャリング (分割代入):
const [first, second] = myArray;
const { name, age } = myObject;
const { country = "Japan" } = myObject;
const { name: userName } = myObject;
function printUser({ name, age }) {}
オプショナルチェイニング (?.
) (ES2020): user?.profile?.address?.street
null
またはundefined
の可能性があるプロパティへの安全なアクセス。Null合体演算子 (??
) (ES2020): const value = possiblyNullOrUndefined ?? "defaultValue";
null
またはundefined
の場合に右辺を返す。||
との違い (空文字列や0を偽と評価しない)。for...of ループ (再確認): イテラブルオブジェクトの反復。
シンボル (Symbol
) (再確認): 一意な値、オブジェクトプロパティキー。
イテレータとジェネレータ (概要):
Symbol.iterator
を持つオブジェクト)。function*
, yield
): イテレータを簡単に作成。全てのオブジェクトはプロトタイプ ([[Prototype]]
または__proto__
) を持つ。
プロパティ/メソッド探索はプロトタイプチェーンを遡る。
Object.getPrototypeOf(obj)
: プロトタイプを取得。
Object.create(proto, propertiesObject)
: 指定したプロトタイプを持つ新しいオブジェクトを作成。
// filepath: (第13章の説明箇所)
const animal = { makeSound: function() { console.log("Generic sound"); } };
const dog = Object.create(animal);
dog.breed = "Labrador";
dog.makeSound(); // "Generic sound" (animalから継承)
コンストラクタ関数のprototype
プロパティ: インスタンスのプロトタイプとなるオブジェクト。
図解必須: インスタンス → コンストラクタのprototype
→ Object.prototype
→ null
。
instanceof
演算子: オブジェクトが特定のコンストラクタのインスタンスか判定。
プロトタイプ汚染の危険性 (Object.prototype
への安易な追加は避ける)。
クラス宣言: class MyClass { ... }
コンストラクタ: constructor(param1) { this.prop1 = param1; }
インスタンス化: const instance = new MyClass(value);
メソッド定義: myMethod() { ... }
ゲッター/セッター: get myProp() { return this._myProp; }
, set myProp(value) { /* validation */ this._myProp = value; }
バリデーション演習:
// filepath: (第13章の説明箇所)
class User { /* ... constructor ... */ set age(value) { if (value < 0) throw new Error("Age must be positive"); this._age = value; } }
静的メソッド/プロパティ: static myStaticMethod() { ... }
, static myStaticProp = value;
継承: class SubClass extends SuperClass { constructor(...) { super(...); /* ... */ } }
super()
: 親クラスのコンストラクタ呼び出し。this
を使う前に必須。super.parentMethod()
: 親クラスのメソッド呼び出し。クラスはプロトタイプベースのシンタックスシュガーであることを再確認。
プライベートクラスフィールド/メソッド (#
) (ES2022): #privateField
, #privateMethod()
。カプセル化。
クラス式: const MyClass = class { ... };
Shape
-> Circle
, Rectangle
)を作成し、インスタンス化、メソッド呼び出し、継承を体験。new Map()
, new Map([['key1', 'val1'], ['key2', 'val2']])
set(key, value)
, get(key)
, has(key)
, delete(key)
, clear()
, size
。keys()
, values()
, entries()
, forEach()
。for...of
も可能。new Set()
, new Set([1, 2, 2, 3])
→ {1, 2, 3}
add(value)
, has(value)
, delete(value)
, clear()
, size
。values()
, entries()
(キーと値が同じ), forEach()
。for...of
も可能。コールバック関数が受け取る引数: callback(currentValue, index, array)
。
forEach(callback)
: 各要素に対して処理を実行 (副作用のため、戻り値なし)。
map(callback)
: 各要素を変換し、新しい配列を生成 (非破壊的)。
filter(callback)
: 条件に合う要素のみを抽出し、新しい配列を生成 (非破壊的)。
reduce(callback, initialValue)
: 配列を単一の値に畳み込む。
具体例: 合計計算、オブジェクトへの変換。
// filepath: (第14章の説明箇所)
const people = [{id:'a', name:'A'}, {id:'b', name:'B'}];
const peopleById = people.reduce((acc, p) => { acc[p.id] = p; return acc; }, {});
find(callback)
: 条件に合う最初の要素を返す。
findIndex(callback)
: 条件に合う最初の要素のインデックスを返す。
some(callback)
: 条件に合う要素が一つでもあればtrue
。
every(callback)
: 全ての要素が条件に合えばtrue
。
flatMap(callback)
(ES2019): map
してから結果をフラット化。
sort(compareFunction)
: 配列をソート (破壊的)。比較関数の重要性。
メソッドチェーン: array.filter(...).map(...).reduce(...)
。
export
):export const myVar = ...;
, export function myFunc() {}
export default function() {}
(ファイルごとに一つのみ)。import
):import { myVar, myFunc } from './myModule.js';
import myDefaultFunc from './myModule.js';
import * as myModule from './myModule.js';
(myModule.myVar
)import { myFunc as anotherName } from './myModule.js';
<script type="module" src="main.js"></script>
。./
, ../
) または絶対パス。module.exports = ...;
, exports.prop = ...;
const myModule = require('./myModule.js');
import/export
vs require/module.exports
。this
の挙動: ESMのトップレベルthis
はundefined
。import()
):const module = await import('./myModule.js');
package.json
: プロジェクト情報、依存関係、スクリプトを記述。name
, version
, description
, main
, scripts
, dependencies
, devDependencies
。npm install <package>
: パッケージインストール。npm run <script-name>
: scripts
に定義したコマンド実行。package-lock.json
/ yarn.lock
: 依存関係のバージョンを固定し、環境再現性を担保。Jest: 多機能なテストフレームワーク。設定少なめ。
Vitest: Viteベースの高速なテストフレームワーク。ESMネイティブサポート。
簡単なアサーション: expect(value).toBe(expectedValue);
// filepath: sum.js
// export function sum(a, b) { return a + b; } // ESM
function sum(a,b) { return a + b; } module.exports = sum; // CJS for basic Jest
// filepath: sum.test.js
// import { sum } from './sum'; // ESM
const sum = require('./sum'); // CJS
describe('sum function', () => {
it('should add two positive numbers', () => {
expect(sum(1, 2)).toBe(3);
});
});
npm test
(または npx jest
, npx vitest
) で実行。
http
: HTTPサーバー/クライアント機能。fs
: ファイルシステム操作。path
: ファイルパス操作。events
: イベント駆動プログラミングの基盤。http.createServer()
を使った基本的な例。npm install express
app.get('/', (req, res) => { ... });
, app.post('/api/data', (req, res) => { ... });
express.json()
: JSONリクエストボディのパース。express.static()
: 静的ファイルの配信。req
): req.params
, req.query
, req.body
。res
): res.send()
, res.json()
, res.status()
。string
, number
, boolean
, null
, undefined
, symbol
, bigint
。number[]
または Array<number>
。{ name: string, age: number }
。any
: 型チェックを無効化 (非推奨、最終手段)。unknown
: any
より安全な型。使用前に型チェックや型アサーションが必要。void
: 関数が何も返さないことを示す。never
: 関数が決して戻らない (常にエラーを投げる、無限ループなど)。interface
) と型エイリアス (type
): オブジェクトの形状を定義。interface User { name: string; age: number; }
type Point = { x: number; y: number; };
interface
は拡張可能 (宣言のマージ、implements
)、type
はより柔軟 (ユニオン型、交差型など)。function add(a: number, b: number): number { return a + b; }
<T>
): 型をパラメータ化し、再利用可能なコンポーネントを作成。function identity<T>(arg: T): T { return arg; }
value as string
または <string>value
(JSXと競合注意)。開発者が型を上書き。|
) と交差型 (&
):string | number
(文字列または数値)。TypeA & TypeB
(TypeAとTypeBの両方の特性を持つ)。tsconfig.json
): コンパイラオプションの設定。tsc
コマンドでTypeScriptコードをJavaScriptコードに変換。tsconfig.json
の設定、ビルドツールとの連携。<nav>
, <main>
, <article>
, <aside>
, <button>
, <h1>
-<h6>
など) を使用する。<div>
や<span>
の乱用を避ける。<img>
タグには適切なalt
属性を設定する。装飾画像ならalt=""
。<label>
と入力要素 (<input>
, <textarea>
, <select>
) を関連付ける (for
属性とid
属性)。エラーメッセージの適切な表示。role
属性、aria-*
属性 (例: aria-label
, aria-hidden
, aria-expanded
)。expect
(Jest/Vitest組み込み), Chai。jest.fn()
: モック関数。呼び出し回数や引数の記録。jest.spyOn(object, 'methodName')
: 既存関数の呼び出しを監視。jest.mock('./module')
: モジュール全体をモック。useState
(React), data
オプション (Vue)。{ type: 'ACTION_TYPE', payload: ... }
)。useSelector
, useDispatch
フック。自己評価と残る懸念 (再掲):
この構成案を元に、各資料の具体的な内容を肉付けしていくことになります。