Skip to content

JavaScript ディープガイド

はじめに

あなたはすでに HTML と CSS を学び、見栄えの良い Web ページを作れるようになりました。しかし、「ボタンをクリックしても反応がない」「フォームを入力しても送信できない」といったことに気づくかもしれません。Web ページはまるで「静的な」画像のようです。

これが JavaScript が必要な理由です——JavaScript は Web ページに「命」を吹き込みます。ボタンをクリックするとメニューが表示され、テキストを入力するとリアルタイム検索ができ、スクロールするとさらにコンテンツが読み込まれます……これらのインタラクティブな効果はすべて JavaScript によって実現されています。

vibecoding では、AI がコードの大部分を書いてくれます。しかし、少なくともコードが何をしているのかを理解できる必要があります。さもなければ、AI が間違ったコードを書いても気づけません。この記事を読めば、次のことができるようになります:

  • AI が書いたコードが何をしているのかを理解する
  • コードのどこに問題があるかを見抜く
  • 明確な言葉で AI に修正方法を伝える

この記事で学ぶこと:

内容学んだ後にできること
第 1 章JavaScript とはWeb ページでどのような役割を果たすかを理解する
第 2 章データと変数プログラムがどのようにデータを保存し、使用するかを知る
第 3 章関数とロジックコードの条件分岐、ループ、再利用のロジックを理解する
第 4 章DOM とイベントコードがどのように Web ページを制御し、ユーザー操作に応答するかを知る
第 5 章実践テクニックAI コードの読み方、エラー遭遇時の伝え方

各章は「コードを識別できる」ことから始まります。手書きできる必要はありません。わからないコードがあれば、いつでもここに戻って確認してください。


1. JavaScript とは

🤔 核心的な問い

なぜ Web ページに JavaScript が必要なのか? HTML と CSS だけで Web ページにコンテンツとスタイルを持たせられるのに、なぜ新しい言語を学ぶ必要があるのか?

1.1 「静的 Web ページ」から「動的アプリケーション」へ

📄 JavaScript がない Web ページ

  • コンテンツは固定され、インタラクション不可
  • ボタンをクリックしても反応がない
  • フォームを入力しても送信できない
  • ページが自動更新されない

まるで紙のポスター、見るだけ

🚀 JavaScript がある Web ページ

  • ボタンをクリックするとメニューが表示される
  • テキストを入力するとリアルタイム検索
  • スクロールで自動的にコンテンツを読み込み
  • データがリアルタイムに更新表示される

まるで本物のアプリケーション

三者関係を一文で理解する:

技術比喩役割
HTML骨格Web ページの構造とコンテンツを定義
CSS皮膚Web ページの外観とスタイルを定義
JavaScript筋肉と神経系Web ページに応答性、インタラクション、思考能力を与える

1.2 なぜ vibecoding でも JavaScript を理解する必要があるのか?

JavaScript を学び始めた開発者のつまずき

JavaScript を学び始めたばかりの開発者が AI で「カウンター」アプリを作りました:ボタンをクリックすると数字が 1 増えます。AI が生成したコードは正常に動作しました。

しかし彼は「クリックで 2 増やす」に変更したくなり、AI に「毎回のクリックで 2 増やして」と伝えました。AI はコードを修正しましたが、数字はまだ 1 しか増えません。

彼は AI に「なぜ効果がないのか」と尋ね、AI は説明しましたが、コード内の count = count + 1 が何を意味するのか理解できず、AI がその箇所を修正したのかどうかもわかりませんでした。「2 増えない」と繰り返すしかなく、AI は何度も修正しましたが、ある時は初期値を 2 に変え、ある時は全く関係ない場所に 2 を足しました。

最終的に彼は第 2 章の「変数」の概念を読んで、count = count + 1 が count の値に 1 を足して再び保存していることを理解しました。そして AI に「count + 1count + 2 に変更して」と伝えました。

一度で修正できました。

これが JavaScript を理解すべき理由です——手書きするためではなく、AI が正しく修正しなかったときに、問題の箇所を一目で見抜き、一言で的確に指摘できるようにするためです。

1.3 まずは覗いてみよう:実際の AI コード

深く学ぶ前に、AI が生成した実際のコードを見てみましょう。理解できなくても心配しないでください。印象だけ持ってもらえれば、後で各部分を一つずつ解説します。

シナリオ:「ボタンをクリックして背景色を切り替える」機能を作る

javascript
// 色のセットを定義
const colors = ['#ff6b6b', '#4ecdc4', '#45b7d1', '#96ceb4']
let currentIndex = 0

// ページ上のボタンを見つける
const button = document.querySelector('#changeBtn')

// ボタンにクリックイベントを追加
button.addEventListener('click', () => {
  currentIndex = (currentIndex + 1) % colors.length
  document.body.style.backgroundColor = colors[currentIndex]
})

このコードは何をしているのか?

コード役割対応する章
const colors = [...]色データのセットを定義第 2 章:配列
let currentIndex = 0現在表示している色の番号を記録第 2 章:変数
document.querySelector(...)ページ上のボタンを見つける第 4 章:DOM 検索
button.addEventListener(...)ボタンにクリックイベントを追加第 4 章:イベントリスニング
() => {...}クリック後に実行するコードを定義第 3 章:アロー関数

💡 核心的な示唆

今すぐすべてのコード行を理解する必要はありません。ただ覚えておいてください:JavaScript コードとは一連の命令であり、「ユーザーが何かをしたとき、何が起こるべきか」をブラウザに伝えるものです。


2. データ編:変数とデータ型

🤔 核心的な問い

プログラムはどのようにして物事を「記憶」するのか? ユーザーの入力内容、サーバーから取得したデータ、計算途中の中間結果——これらの情報はどこに保存されているのか?

2.1 変数:データに名前を付ける

変数はラベル付きの箱のようなもの——データを中に入れて、後でラベルを通じて取り出すことができます。

javascript
const name = "田中"   // 名前は変わらないので const
let age = 25          // 年齢は変わる可能性があるので let

なぜ const と let を区別するのか?

想像してみてください:あなたのマイナンバー(const)は生涯変わりませんが、年齢(let)は毎年変わります。JavaScript では、異なるキーワードを使ってこの「変わるものと変わらないもの」の意図を表現します。

キーワード変更可否使用シーン
const❌ 不可値が変わらないデータマイナンバー、設定項目、色リスト
let✅ 可値が変わるデータカウンター、現在選択中のオプション、ユーザー入力
🔍 具体的な例を見てみよう
javascript
// const を使用:これらの値は変わらない
const PI = 3.14159
const MAX_USERS = 100
const APP_NAME = "TodoList"

// let を使用:これらの値は変化する
let count = 0
count = 1  // ✅ 変更可能

count = count + 1  // ✅ 元の値に基づいて計算可能

// const を使うとどうなる?
const fixedCount = 0
fixedCount = 1  // ❌ エラー!const は再代入できない

👇 実際に試してみよう:以下のコードを修正して、const と let の違いを観察してください

📦 变量就像带名字的盒子
const
name
张三
🔒
let
age
25
🔓
const
isStudent
true
🔒
const name = "张三"let age = 25

2.2 データ型:JavaScript におけるいくつかの「もの」

JavaScript はデータをいくつかの型に分類します。最もよく使われるのは次の 3 つです:

説明実際のシーン
string(文字列)テキストコンテンツ"hello", 'こんにちは'ユーザー名、商品説明、メッセージ
number(数値)数値42, 3.14価格、数量、評価
boolean(真偽値)はい/いいえtrue, falseログイン済みか、完了したか、表示可能か

知っておくべき 2 つの特殊な値:

  • undefined → 変数は宣言されたが、まだ値が代入されていない
  • null → 意図的に空に設定(「ここには値がない」ことを示す)
🔍 テンプレート文字列:より便利なテキスト結合

AI コードでは、バッククォート(`)で囲まれ、中に ${...} を含む文字列をよく見かけます:

javascript
const name = "田中"
const age = 25

// 従来の書き方(面倒)
const message = "私は" + name + "、今年" + age + "歳です"

// テンプレート文字列(簡潔)
const message = `私は${name}、今年${age}歳です`
// 結果:"私は田中、今年25歳です"

識別のポイント:バッククォートと ${} を見たら、変数をテキストに埋め込んでいるのだとわかります。

2.3 オブジェクトと配列:データを整理する

オブジェクト = 名前付きプロパティのセット(個人情報表のようなもの)

javascript
const user = {
  name: "田中",
  age: 25,
  isVIP: true
}

// ドット記法でプロパティにアクセス
console.log(user.name)    // "田中"
console.log(user.age)     // 25

配列 = 順序付きデータのセット(リストのようなもの)

javascript
const colors = ['赤', '緑', '青']

// インデックスでアクセス(0 から始まる)
console.log(colors[0])  // "赤"
console.log(colors[1])  // "緑"

ネスト構造:オブジェクトの中に配列、配列の中にオブジェクト

これは AI コードで最も一般的なデータ構造です:

javascript
const todos = [
  { id: 1, text: "JavaScript を学ぶ", done: false },
  { id: 2, text: "プロジェクトを作る", done: true },
  { id: 3, text: "ドキュメントを書く", done: false }
]

// アクセス:まず配列の 0 番目を取り、その text プロパティを取得
console.log(todos[0].text)  // "JavaScript を学ぶ"

💡 識別のコツ

  • {} を見たら → これはオブジェクト、中身は 名前: 値 のセット
  • [] を見たら → これは配列、中身は順序付けられた値のセット
  • data[0].name を見たら → まず配列の 0 番目を取り、その name プロパティを取得

2.4 値と参照:ハマりやすい落とし穴

これは初心者が最もよく遭遇する問題の一つです!

基本型(string、number、boolean)の代入 = まったく新しいデータのコピー:

javascript
let a = 10
let b = a      // b は a のコピーを取得
b = 20
console.log(a) // 10(a は影響を受けない)

オブジェクトと配列の代入 = 「アドレス」をコピー(同じものを指す):

javascript
let user1 = { name: "田中" }
let user2 = user1      // user2 は同じオブジェクトを指す
user2.name = "佐藤"     // user2 の変更が user1 に影響する
console.log(user1.name) // "佐藤"(user1 も変わった!)

なぜコピーを作成するのか?

React/Vue では、データを直接変更すると画面が更新されません。そのため AI コードではよく [...array]{...obj} を見かけます——これはコピーを作成し、相互影響を防いでいます。

javascript
// スプレッド演算子でコピーを作成
const arr1 = [1, 2, 3]
const arr2 = [...arr1]     // 新しい配列を作成
arr2.push(4)
console.log(arr1)          // [1, 2, 3](影響を受けない)
console.log(arr2)          // [1, 2, 3, 4]

👇 実際に試してみよう:コピーを変更したときの元データの変化を観察してください

🔄 值 vs 引用
基本类型(复制值)
a10
b?
点击复制
引用类型(复制地址)
obj10x001
obj2?
0x001
{ age: 25 }
点击复制
基本类型
let a = 10
let b = a  // b=10
b = 20     // a还是10
引用类型
let obj1 = {age:25}
let obj2 = obj1
obj2.age=30 // obj1也变了!
// 用 {...obj1} 复制

2.5 分割代入とスプレッド:モダン JavaScript のショートカット記法

この 2 つの構文は AI コードのあちこちに登場します。知らないとコードが読めません。

分割代入:オブジェクトや配列からデータを素早く抽出

javascript
const user = { name: "田中", age: 25, city: "東京" }

// 従来の書き方(面倒)
const name = user.name
const age = user.age

// 分割代入の書き方(簡潔)
const { name, age } = user
// 効果は同じだが、一行で完了

スプレッド演算子:コピーしてデータを拡張

javascript
// 配列をコピーして新しい要素を追加
const arr1 = [1, 2, 3]
const arr2 = [...arr1, 4, 5]  // [1, 2, 3, 4, 5]

// オブジェクトをコピーして新しいプロパティを追加
const user1 = { name: "田中", age: 25 }
const user2 = { ...user1, city: "東京" }
// { name: "田中", age: 25, city: "東京" }

💡 識別のコツ

  • const { name, age } = person を見たら → person オブジェクトから name と age を抽出
  • ...array...obj を見たら → 配列やオブジェクトを展開して平らにしている
  • 手書きできる必要はないが、読める必要はある

3. ロジック編:関数とフロー制御

🤔 核心的な問い

コードはどのように「判断」し「繰り返し処理」をするのか? プログラムは条件に応じて異なる操作を実行し、特定のタスクを繰り返し実行する必要があります——これらのロジックはどのように表現するのか?

3.1 条件分岐:もし...なら...そうでなければ...

if/else:最も基本的な条件分岐

javascript
const age = 18

if (age >= 18) {
  console.log("成人")
} else {
  console.log("未成年")
}

三項演算子:if/else の省略形

javascript
// 完全な書き方(4 行)
let message
if (age >= 18) {
  message = "成人"
} else {
  message = "未成年"
}

// 三項演算子(1 行)
const message = age >= 18 ? "成人" : "未成年"
// 形式:条件 ? 条件が真の場合の値 : 条件が偽の場合の値

&& 短絡評価:React コードでよく見かける

javascript
// isLoggedIn が true の場合のみユーザーパネルを表示
isLoggedIn && <UserPanel />

// 以下と同等
if (isLoggedIn) {
  return <UserPanel />
}

💡 識別のコツ

  • ? : を見たら → これは三項演算子、if/else の省略形
  • && を見たら → 前が true の場合のみ後ろを実行

3.2 関数:操作をパッケージ化する

関数 = 料理のレシピ

  • 関数を定義 = レシピを書き留める
  • 関数を呼び出す = レシピ通りに料理を作る
  • パラメータ = 材料
  • 戻り値 = 完成品
javascript
// 関数を定義(レシピを書き留める)
function greet(name) {
  return "Hello " + name
}

// 関数を呼び出す(レシピ通りに料理を作る)
console.log(greet("田中"))  // "Hello 田中"
console.log(greet("佐藤"))  // "Hello 佐藤"

3 つの書き方、一目で識別:

javascript
// 1. function 宣言(従来の書き方)
function greet(name) {
  return "Hello " + name
}

// 2. アロー関数(AI コードで最もよく使われる)
const greet = (name) => {
  return "Hello " + name
}

// 3. アロー関数の省略形(1 行のみの場合)
const greet = (name) => "Hello " + name

👇 実際に試してみよう:異なる名前を入力して、関数がどのように動作するか観察してください

函数就像一台机器

参数(输入)

函数

calculatePrice
price * discount

返回值(输出)

?

当前函数定义

const calculatePrice = (price, discount) => {
  return price * discount
}

// 或者更简洁:
const calculatePrice = (price, discount) => price * discount

💡 識別のコツ

  • function または => を見たら → これは関数
  • fn() を見たら → この関数を呼び出している
  • () => {} を見たら → アロー関数、モダン JS の主流の書き方

3.3 配列メソッド:リスト処理の強力なツール

React/Vue では、ほぼすべてのリストレンダリングでこれらのメソッドが使われます。

javascript
const todos = [
  { id: 1, text: "学習", done: false },
  { id: 2, text: "仕事", done: true }
]

// .map():配列の各要素を別のものに変換
const texts = todos.map(todo => todo.text)
// ["学習", "仕事"]

// .filter():条件に合う要素をフィルタリング
const unfinished = todos.filter(todo => !todo.done)
// [{ id: 1, text: "学習", done: false }]

// .find():条件に合う最初の要素を見つける
const found = todos.find(todo => todo.id === 1)
// { id: 1, text: "学習", done: false }

💡 識別のコツ

  • .map() を見たら → 配列を変換し、新しい配列を返す
  • .filter() を見たら → 配列をフィルタリング
  • items.map(item => <li>{item.name}</li>) を見たら → 各データ項目をリストタグに変換

3.4 スコープ:変数の「可視範囲」

「部屋」の比喩で:

  • 関数内部の変数は部屋の中の物のようなもので、外からは見えない
  • でも部屋の中にいる人は廊下(外側のスコープ)の物を見ることができる
javascript
const global = "グローバル変数"  // 廊下にある物

function room() {
  const local = "部屋の中の物"  // 部屋の中の物
  console.log(global)  // ✅ 廊下が見える
}

console.log(local)  // ❌ エラー!外からは部屋の中の物が見えない

核心的な直感: コードがどこに書かれているかが、どの変数を見られるかを決定します。

👇 実際に試してみよう:異なるスコープをクリックして、どの変数にアクセスできるか観察してください

🔍 作用域:变量的"可见范围"

全局作用域
appName= "Todo"
函数 greet() 作用域
appName= "Todo"← 全局
message= "你好"
if 块作用域
appName= "Todo"← 全局
message= "你好"← 函数
greeting= message+appName
💡 当前位置可见的变量
在全局作用域,只能使用全局变量 appName

对应代码

const appName = "Todo"  // 全局作用域

function greet() {
  const message = "你好"  // 函数作用域

  if (true) {
    const greeting = message + appName  // 块级作用域
    console.log(greeting)
  }

  console.log(greeting)  // ❌ 报错!外层看不到内层
}

3.5 クロージャ:関数が生まれた環境を「記憶」している

独立した概念としてではなく、具体的なシーンから理解しましょう:

javascript
function setupCounter() {
  let count = 0  // この変数は関数の内部にある

  return {
    add: () => { count++; return count },
    getCount: () => count
  }
}

const counter = setupCounter()
console.log(counter.add())      // 1
console.log(counter.add())      // 2
console.log(counter.getCount()) // 2

核心的な直感: 関数は作成されるときに、周囲の変数を「記憶」します。外側の関数の実行が終了しても、その記憶は保持されます。

👇 実際に試してみよう:クロージャがどのように関数に状態を「記憶」させるか観察してください

🎁函数与闭包理解作用域链和闭包机制
想象你有个背包(函数),每次出门时都会把当时看到的 风景(外部变量)装进去。 闭包就是这个背包——即使离开了那个地方,你依然能拿出当时装的风景
函数声明方式
// 1. 函数声明
function greet(name) {
return "Hello " + name
}
// 2. 函数表达式
const greet = function(name) {
return "Hello " + name
}
// 3. 箭头函数 (ES6)
const greet = (name) => {
return "Hello " + name
}
// 简化版(单行可省略 return)
const greet = name => "Hello " + name
试试调用函数
点击"调用"按钮看结果...
💡核心思想:函数是 JavaScript 中的一等公民,可以赋值给变量、作为参数传递、作为返回值。箭头函数更简洁,且不绑定自己的 this。

3.6 this:関数が誰に呼ばれたか

複雑なバインディングルールではなく、最も一般的なシーンだけを説明します:

シーン 1:オブジェクトのメソッド内では、this はそのオブジェクトを指す

javascript
const user = {
  name: "田中",
  sayHi() {
    console.log("こんにちは、私は" + this.name)  // this は user を指す
  }
}
user.sayHi()  // "こんにちは、私は田中"

シーン 2:イベントリスナー内では、this はイベントを発生させた要素を指す

javascript
button.addEventListener('click', function() {
  console.log(this)  // this は button 要素を指す
})

// ただしアロー関数は this を変更しない
button.addEventListener('click', () => {
  console.log(this)  // this は外側の this を指す
})

💡 問題が起きたら?

AI コードに this 関連のバグが出た場合(例:Cannot read property of undefined)、AI にこう伝えてください:「このメソッドの this の参照先が正しくありません。アロー関数に変更するか、bind を使ってください」


4. インタラクション編:DOM、イベントと非同期

🤔 核心的な問い

JavaScript はどのように Web ページと「対話」するのか? ページ上の要素をどうやって見つけるのか? ユーザーのクリックや入力にどう応答するのか? サーバーからどうやってデータを取得するのか?

4.1 DOM:JavaScript から見た Web ページ

Web ページは JavaScript の目には「木」として映り、各 HTML タグは木の上の「ノード」です。

html
<html>
  <body>
    <h1>タイトル</h1>
    <p>段落</p>
    <ul>
      <li>項目1</li>
      <li>項目2</li>
    </ul>
  </body>
</html>

JS で Web ページを操作 = ノードを見つける + ノードを変更する + ノードを作成/削除する

👇 実際に試してみよう:ノードをクリックして、DOM ツリーがどのように構成されているか観察してください

DOM 树:JavaScript 看到的网页

我的网页

欢迎光临

  • 项目1
  • 项目2
<html>
<body>
<h1>我的网页
<p>欢迎光临
<ul>
<li>项目1
<li>项目2

对应代码

点击上方按钮查看对应代码

4.2 要素の検索と変更

要素の検索:

javascript
// CSS セレクタで検索(最も一般的)
const title = document.querySelector('h1')      // 最初の h1 を探す
const button = document.querySelector('#btn')   // id="btn" の要素を探す
const items = document.querySelectorAll('.item') // class="item" の全要素を探す

要素の変更:

javascript
// テキストを変更
title.textContent = "新しいタイトル"

// スタイルを変更
element.style.color = "red"
element.style.fontSize = "20px"

// CSS クラスを変更
element.classList.add('active')      // クラスを追加
element.classList.remove('hidden')   // クラスを削除
element.classList.toggle('open')     // クラスを切り替え(あれば削除、なければ追加)

💡 識別のコツ

  • document.querySelector を見たら → Web ページの要素を検索している
  • .textContent を見たら → テキストを変更
  • .style.xxx を見たら → スタイルを変更
  • .classList.add/remove/toggle を見たら → CSS クラスを変更

4.3 イベント:ユーザーが特定の操作をしたとき...

addEventListener:要素にイベントリスナーを追加

javascript
button.addEventListener('click', () => {
  console.log("ボタンがクリックされました")
})

一般的なイベント:

イベント発生タイミング実際のシーン
clickクリックボタンクリック、リンク遷移
input入力欄の内容が変化リアルタイム検索、フォームバリデーション
submitフォーム送信ログイン、登録、データ送信
scrollページスクロール遅延読み込み、トップに戻る

イベントオブジェクト:より多くの情報を取得

javascript
input.addEventListener('input', (e) => {
  console.log(e.target.value)  // 入力欄の値を取得
  e.preventDefault()            // デフォルト動作を防止(例:フォーム送信後のページリフレッシュ)
})

💡 実践への応用

ボタンに機能を追加したいとき、本質的には AI にこう伝えることです:「このボタンにクリックイベントを追加して、クリックされたら特定の操作を実行してください」

4.4 非同期:なぜ一部の操作はすぐに完了しないのか

レストランの比喩:

注文した後、キッチンの前で待つ必要はありません。先に他のことをして、料理ができたらウェイターが運んできてくれます。

最も一般的なシーン:サーバーからデータを取得

javascript
// 同期の書き方(ページが固まるので使わないで)
const data = fetch('/api/data')  // ❌ この書き方では固まる

// 非同期の書き方(正しい)
async function loadData() {
  try {
    const response = await fetch('/api/data')
    const data = await response.json()
    console.log(data)
  } catch (error) {
    console.error('エラーが発生しました:', error)
  }
}

async/await 構文:

  • async → この関数内に非同期操作があることをマーク
  • await → この操作の完了を待つ(ただしページは固まらない)
  • try/catch → 発生する可能性のあるエラーを処理

👇 実際に試してみよう:非同期操作の実行順序を観察してください

异步:同步 vs 异步

厨房

灶位 1
空闲
灶位 2
空闲
灶位 3
空闲

顾客

👤
顾客 A
煮面 (2秒)
👤
顾客 B
炒饭 (3秒)
👤
顾客 C
烤鱼 (5秒)

代码对比

同步(阻塞)
console.log("1")
console.log("2")  // 等上面执行完
console.log("3")
// 输出:1, 2, 3
异步(不阻塞)
console.log("1")
setTimeout(() => console.log("2"), 1000)
console.log("3")
// 输出:1, 3, 2

💡 識別のコツ

  • async/await を見たら → 時間のかかる操作を待っている
  • fetch() を見たら → サーバーからデータを取得している
  • try/catch を見たら → 発生する可能性のあるエラーを処理している

4.5 イベントループ:JavaScript は実際にどう動くのか

「マイクロタスク/マクロタスク」といった用語は使わず、シンプルなモデルで理解しましょう:

JS は「一人用の作業机」で、同時に一つのことしかできませんが、「TODO 付箋ボード」(タスクキュー)があります。

待つ必要がある操作(ネットワークリクエスト、タイマー)に遭遇すると、JS は愚直に待つのではなく、「待ち終わったら何をするか」を付箋に書いて貼り、自分はそのまま実行を続けます。現在の処理が終わってから、付箋ボードを確認します。

javascript
console.log("1")

setTimeout(() => console.log("2"), 0)  // 0 秒でも、後回しにされる

console.log("3")

// 出力:1, 3, 2(1, 2, 3 ではない!)

なぜか?

  1. console.log("1") を実行 → 1 を出力
  2. setTimeout に遭遇 → コールバックを付箋ボードに貼り、続行
  3. console.log("3") を実行 → 3 を出力
  4. 現在のコードの実行が完了、付箋ボードを確認
  5. setTimeout のコールバックを実行 → 2 を出力

👇 実際に試してみよう:コードの実行順序を観察してください

事件循环:JavaScript 的执行机制

代码队列

1
console.log("1")
执行中
2
setTimeout(() => console.log("2"), 0)
3
console.log("3")
4
fetch("/api").then(() => console.log("4"))
5
console.log("5")

工位(单线程)

👨‍💻
正在执行
执行 console.log("1")

便签栏(任务队列)

暂无待办任务

输出日志

等待输出...

执行顺序:还未开始

代码书写顺序:1, 2, 3, 4, 5

代码从上到下写的,但执行顺序不一定从上到下——因为异步操作会被"推迟"到当前代码执行完之后。

💡 問題が起きたら?

AI コードでデータがまだ取得できていないのにページがレンダリングされた場合、AI にこう伝えてください:「データの読み込みが完了する前にレンダリングが始まっています。loading 状態を追加して、データが到着してからレンダリングするようにしてください」

4.6 モジュール:import と export

AI が生成した React/Vue コードの最初の行はほぼ常に import です。

import = 他のファイルから機能を読み込む

javascript
// ユーティリティファイルから関数を読み込む
import { formatDate } from './utils'

// サードパーティパッケージから読み込む
import React from 'react'
import { useState } from 'react'

export = 機能を外部に公開して他の人が使えるようにする

javascript
// utils.js
export function formatDate(date) {
  // ...
}

// またはデフォルトエクスポート
export default function formatDate(date) {
  // ...
}

npm パッケージ = 他の人が書いたツール、インストールすれば使える

javascript
// パッケージをインストール:npm install lodash
// パッケージを使用
import _ from 'lodash'

💡 識別のコツ

  • import を見たら → 他のファイルから機能を読み込んでいる
  • export を見たら → 機能を外部に公開している
  • from 'react' を見たら → React パッケージから読み込んでいる
  • from './utils' を見たら → ローカルファイルから読み込んでいる

5. 実践編:コードを読む、エラーを理解する、正確に説明する

🤔 核心的な問い

ここまで多くの構文を学んだが、実際に AI のコードを手にしたときどう使うのか? どうやって素早くコードを読み解くのか? エラーに遭遇したらどうするのか? どうやって AI に正確にコードを修正してもらうのか?

5.1 AI コードを手にしたらどう読むか

4 ステップ法:

ステップ何を見るか
第一步:全体構造を見る関数はいくつあるか?それぞれ何をするか?loadData() はデータ読み込み、renderList() はリスト表示
第二步:エントリポイントを探すプログラムはどこから実行を開始するか?addEventListener('click', ...) クリック時に開始
第三步:データフローを追跡データはどこから来て、どこに行くか?API から取得 → 解析 → ページにレンダリング
第四步:詳細ロジックを見る具体的な関数内でどう処理しているか?ループ、判断、計算

第 1 章のコード例で完全な「読み方デモ」をやってみましょう:

javascript
// 第一步:全体構造
// - 色の配列
// - 現在のインデックスを記録する変数
// - ボタンのクリックイベント

// 第二步:エントリポイント
// button.addEventListener('click', ...) → ボタンクリック時に実行

// 第三步:データフロー
// colors(色配列)→ currentIndex(現在のインデックス)→ backgroundColor(背景色)

// 第四步:詳細ロジック
// currentIndex = (currentIndex + 1) % colors.length
// この式の意味:毎回 +1 するが、配列の長さを超えない(循環)

5.2 よくあるエラークイックリファレンス

エラー平易な説明AI への伝え方
TypeError: Cannot read properties of undefined存在しないものから値を取得しようとしている「X 行目でエラー、変数 XXX が undefined です。代入ロジックを確認してください」
ReferenceError: xxx is not defined宣言されていない変数名を使っている「変数 xxx が定義されていません。スペルミスかインポート忘れではないですか」
TypeError: xxx is not a function関数ではないものを関数として呼び出している「xxx は関数ではありません。その型と出所を確認してください」
SyntaxError: Unexpected token構文エラー(括弧の不一致、カンマ忘れなど)「X 行目に構文エラーがあります。括弧と句読点を確認してください」
CORS errorブラウザがクロスオリジンリクエストをブロック「CORS エラーが発生しました。クロスオリジンリソース共有を設定する必要があります」
404 Not Foundリクエストしたリソースが存在しない「API が 404 を返しています。エンドポイントのアドレスが正しいか確認してください」

5.3 問題を正確に説明する方法

初心者と熟練開発者の差は、往々にして問題説明の正確さに現れます。

❌ 悪い説明✅ 良い説明
「コードにバグがある」「削除ボタンをクリックすると、現在の項目ではなく最後の項目が削除されます」
「スタイルがおかしい」「タイトルが中央揃えになるべきですが、左揃えになっています」
「データが表示されない」「fetch リクエストはデータを返していますが(コンソールで確認できます)、ページが再レンダリングされていません」
「機能を追加して」「ユーザー一覧ページに検索ボックスを追加して、入力時に name フィールドで曖昧一致するようにリストをリアルタイムフィルタリングしてください」
「クリックしても反応がない」「ボタンをクリックするとコンソールに 'Cannot read property of undefined' エラーが表示され、エラーは X 行目です」

実践練習:

javascript
// バグのあるコード
function deleteTodo(index) {
  todos.splice(index, 1)  // 常に最後の項目を削除してしまう
}

// エラー現象:どの削除ボタンを押しても、最後の項目が削除される

❌ 悪い説明: 「削除機能にバグがある」

✅ 良い説明: 「削除ボタンをクリックすると、現在の項目ではなく最後の項目が削除されます。コードでは splice(index, 1) を使っていますが、index が正しくない可能性があります。各項目の一意な id を使って削除対象をマッチングするように変更する必要があります。」

5.4 あなたが今識別できるようになったコード

  • const/let を見たら → 変数が再代入可能かどうかがわかる
  • {} を見たら → オブジェクト / [] を見たら → 配列
  • {...obj}[...arr] を見たら → コピーを作成している
  • function=> を見たら → 繰り返し実行可能な操作を定義している
  • if/else? : を見たら → コードが判断を行っている
  • .map() / .filter() を見たら → 配列を変換またはフィルタリングしている
  • document.querySelector を見たら → Web ページの要素を検索している
  • addEventListener を見たら → ユーザー操作を監視している
  • async/await を見たら → 時間のかかる操作を待っている
  • import/export を見たら → モジュールを読み込みまたはエクスポートしている
  • エラーに遭遇したら → 大意を読み取り、AI に正確に説明できる

各章の「深掘り」部分をしっかり読んだなら、以下の核心概念も習得しています:

  • 値 vs 参照:基本型は値をコピーし、オブジェクト/配列はアドレスをコピーする
  • スコープとクロージャ:関数は生まれたときの周囲の変数を「記憶」できる
  • this の本質:関数がどこに書かれているかではなく、誰に呼ばれたかで決まる
  • イベントループ:JS はシングルスレッドで、タスクキューによって「ブロックしない」を実現する

これらの概念は、問題の特定をより速くします。

💡 問題が起きたら AI にこう伝えよう

  • 「X 行目でエラー XXX が出ています。何が問題か見てもらえますか」
  • 「この関数のロジックは XXX のはずですが、結果が違います。正しくは XXX であるべきです」
  • 「XXX 機能を修正したいです。具体的な要件は XXX です」