STEP 3 / JAVASCRIPT

読んで、決めて、
書き換える

JavaScript がやることは、突き詰めるとこの 3 つだけです。値を読み、条件で分岐し、画面や状態を書き換える。文法はその手段にすぎません。実行結果をその場に出しながら、順番に見ていきます。

目次を開く(全 17 章)

黒い枠は console.log() の出力です。「↻ 実行」でその場のコードをもう一度動かせます。

01

JavaScript の置き方

HTML から読み込むだけです。defer を付けて <head> に置くのが今の定番。これで「HTML を全部読み終えてから実行」されるので、要素が見つからないエラーを防げます。

HTML
<head>
  <script src="assets/javascripts/main.js" defer></script>
</head>

書いた結果を確かめるには console.log() を使います。ブラウザで F12(Mac は ⌘ + Option + I)を押すと開発者ツールが開き、「コンソール」タブに出力されます。これが最初にして最強のデバッグ道具です。

JavaScript
console.log('こんにちは、JavaScript');
console.log(1 + 2);
console.log('今日の日付:', new Date().toLocaleDateString('ja-JP'));

このページでは、コンソールの代わりに上の黒い枠へ出力しています。

02

変数 — const と let

値に名前を付けて取っておく箱です。宣言は 2 つだけ覚えます。 まず const。あとで入れ替えるものだけ let 古い var は使いません。

JavaScript
const name = '山田';        // 入れ替えない
let count = 0;              // あとで増える

count = count + 1;
count += 1;                 // 同じ意味の短い書き方
console.log(name, count);

// const でも「中身」は変えられる(箱を差し替えられないだけ)
const scores = [10, 20];
scores.push(30);
console.log(scores);

// ブロック { } の外からは見えない
{
  const secret = 'ここだけ';
  console.log(secret);
}
// console.log(secret);  ← ここで使うとエラーになる
なぜ var を使わないのか

var はブロック { } を無視して外まで漏れ出し、同じ名前で何度でも宣言できてしまいます。 const / let はブロックの中だけで有効なので、 取り違えのバグが起きません。名前は userName のように、意味が分かる英単語で。

03

データ型

扱える値の種類です。まずはこの 7 つ。typeof で種類を調べられます。

JavaScript
const text = 'あいうえお';         // 文字列 string
const price = 1280;               // 数値 number(整数も小数も同じ)
const isOpen = true;              // 真偽値 boolean
const nothing = null;             // 「空」だと明示した状態
let notSet;                       // undefined(まだ入れていない)

const list = ['赤', '青', '緑'];   // 配列 array
const user = { name: '山田', age: 30 };  // オブジェクト object

console.log(typeof text, typeof price, typeof isOpen);
console.log(typeof nothing, typeof notSet);
console.log(list.length, list[0]);
console.log(user.name, user['age']);

// 文字列の中に値を埋め込む(テンプレートリテラル)
console.log(`${user.name}さんは${user.age}歳、商品は${price.toLocaleString()}円`);

typeof null'object' になるのは JavaScript の古い不具合で、直せないまま残っています。

04

演算子と比較

計算と比較の記号です。比較のうち等価判定は 必ず ===!==(型まで見るほう)を使います。 == は型を勝手に変換して比べるため、直感に反する結果になります。

記号意味
+ - * /足す・引く・かける・割る3 + 4 → 7
%割った余り(偶数判定によく使う)10 % 3 → 1
**べき乗2 ** 10 → 1024
< >より小さい・より大きい2 < 5 → true
<= >=以下・以上(等しい場合を含む)5 >= 5 → true
===型も値も等しい1 === '1' → false
!==型か値が違う(=== の否定)1 !== '1' → true
&& || !かつ・または・否定a > 0 && a < 10
JavaScript
// 四則演算
console.log(3 + 4, 10 - 4, 6 * 7);   // 7 6 42
console.log(10 / 3);                 // 3.333…(整数どうしでも小数になる)
console.log(10 % 3);                 // 1(余り)
console.log(2 ** 10);                // 1024(べき乗)

// + は文字列の連結にもなる。数値と混ぜると文字列になってしまう
console.log('合計' + 100, '1' + 1, '1' - 1);   // 合計100 / 11 / 0

// 大小の比較
console.log(2 < 5, 5 > 5, 5 >= 5, 5 <= 4);   // true false true false

// 等しい/等しくない。型まで見るこの 2 つを使う
console.log(1 === 1, 1 === '1');             // true false
console.log(1 !== 2, 1 !== '1');             // true true
console.log(1 == '1', 1 != '1');             // true false ← 型を無視するので危険

// 組み合わせる
const age = 20;
console.log(age >= 18 && age < 65);          // かつ
console.log(age < 18 || age >= 65);          // または
console.log(!(age >= 18));                   // 否定

// 偽とみなされる値(falsy)はこの 6 つだけ
for (const value of [false, 0, '', null, undefined, NaN]) {
  console.log(value, '→', Boolean(value));
}

// ?? は「null か undefined のときだけ」右を使う
const input = 0;
console.log(input || 10);   // 10  ← 0 も偽なので置き換わってしまう
console.log(input ?? 10);   // 0   ← こちらが意図どおり

// ?. は途中が無ければ undefined を返す(エラーで止まらない)
const data = { user: { name: '山田' } };
console.log(data.user?.name);
console.log(data.company?.name);

05

制御構文

「条件で分ける」「繰り返す」。プログラムの流れを決める部分です。

JavaScript
const score = 78;

if (score >= 90) {
  console.log('優');
} else if (score >= 70) {
  console.log('良');
} else {
  console.log('可');
}

// 短い分岐は三項演算子で 1 行に
console.log(score >= 60 ? '合格' : '不合格');

// 値で分けるなら switch
const day = 'sat';
switch (day) {
  case 'sat':
  case 'sun':
    console.log('休み');
    break;              // break を忘れると次に流れ込む
  default:
    console.log('平日');
}

// 配列を回すなら for...of が読みやすい
for (const fruit of ['りんご', 'みかん']) {
  console.log(fruit);
}

// 回数を数えるなら for
for (let i = 1; i <= 3; i++) {
  if (i === 2) continue;   // この回だけ飛ばす
  console.log(`${i} 回目`);
}

// 番号も欲しいときは entries()
for (const [index, name] of ['A', 'B'].entries()) {
  console.log(index, name);
}

06

配列とよく使うメソッド

配列は「順番に並んだ値の入れ物」です。まずは回し方を 3 つ覚えます。 for 文、for...of、そして forEach。どれも「1 つずつ順番に処理する」という同じことをしています。

JavaScript
const fruits = ['りんご', 'みかん', 'ぶどう'];

// 1. for 文:番号(添字)を自分で進める。いちばん基本の形
for (let i = 0; i < fruits.length; i++) {
  console.log(i, fruits[i]);
}

// 2. for...of:番号が要らないなら、こちらが読みやすい
for (const fruit of fruits) {
  console.log(fruit);
}

// 3. forEach:配列に「1 つずつ処理して」と頼む。2 つめの引数が番号
fruits.forEach((fruit, index) => {
  console.log(`${index + 1} 番目:${fruit}`);
});

// for と for...of は途中で抜けられる
for (const fruit of fruits) {
  if (fruit === 'みかん') break;   // ここで終わり
  console.log('見つける前:', fruit);
}
書き方向いている場面途中で抜けられる
for番号を使う。逆順や 2 つ飛ばしなど、進み方を細かく決めたいときできる(break
for...of中身だけ順番に見たいとき。ふだんはこれできる(break
forEach1 つずつ処理するだけのとき。メソッドをつなげて書けるできない
forEach で break はできない

forEach の中で break は書けず、return を書いてもその 1 回分を飛ばすだけです(continue と同じ働き)。途中で打ち切りたいときは for...of を使ってください。

名前の付いた処理に置き換える

回すことに慣れたら、次はメソッドです。「変換するなら map」「絞り込むなら filter」のように やりたいことが名前で分かるので、コメントが要らなくなります。まずは map / filter / find / reduce の 4 つ。

JavaScript
const items = [
  { name: 'えんぴつ', price: 120, stock: 5 },
  { name: 'ノート', price: 280, stock: 0 },
  { name: '消しゴム', price: 90, stock: 12 }
];

// map:全部を別の形に変える(個数は変わらない)
console.log(items.map((item) => item.name));

// filter:条件に合うものだけ残す
console.log(items.filter((item) => item.stock > 0).map((i) => i.name));

// find:最初の 1 つを探す(無ければ undefined)
console.log(items.find((item) => item.price < 100));

// reduce:ひとつの値にまとめる(合計・最大など)
const total = items.reduce((sum, item) => sum + item.price, 0);
console.log('合計', total);

// some / every:ひとつでも / 全部が
console.log(items.some((i) => i.stock === 0), items.every((i) => i.price > 50));

// 元の配列を壊さない並べ替え(toSorted)
const byPrice = items.toSorted((a, b) => a.price - b.price);
console.log(byPrice.map((i) => i.price), items.map((i) => i.price));

// at(-1) で最後の要素
console.log(['春', '夏', '秋', '冬'].at(-1));

// includes / join / スプレッド
console.log(['赤', '青'].includes('青'), ['赤', '青'].join(' と '));
console.log([...[1, 2], ...[3, 4]]);

sort() は元の配列を並べ替えてしまいます。toSorted() は新しい配列を返すので、元を壊しません。

07

オブジェクト

「名前と値」の組を束ねたものです。関連するデータをひとまとめにするときに使います。

JavaScript
const user = { name: '山田', age: 30, city: '大阪' };

// 分割代入:必要なものだけ取り出す
const { name, city } = user;
console.log(name, city);

// 名前を変えて取り出す/既定値を付ける
const { name: userName, country = '日本' } = user;
console.log(userName, country);

// 配列も同じように取り出せる
const [first, second] = ['金', '銀'];
console.log(first, second);

// スプレッドで複製しつつ一部を上書き(元は壊さない)
const updated = { ...user, age: 31 };
console.log(updated, user.age);

// 省略記法:変数名とキー名が同じなら 1 回でよい
const age = 31;
console.log({ name, age });

// 一覧として回す
for (const [key, value] of Object.entries(user)) {
  console.log(`${key}:${value}`);
}
console.log(Object.keys(user), Object.values(user));

08

関数

処理に名前を付けて、何度でも呼べるようにしたものです。書き方は 2 通りありますが、意味はほぼ同じ。使い分けの目安も添えます。

JavaScript
// 関数宣言。呼び出しより後ろに書いてもよい(巻き上げ)
function greet(name) {
  return `${name}さん、こんにちは`;
}

// アロー関数。式なので、書いた後でしか使えない
const double = (n) => n * 2;              // { } と return を省略できる
const area = (w, h) => {
  const size = w * h;
  return size;
};

console.log(greet('山田'), double(21), area(3, 4));

// 既定値。渡されなければこれを使う
const tax = (price, rate = 0.1) => Math.round(price * (1 + rate));
console.log(tax(1000), tax(1000, 0.08));

// 残り全部を配列で受け取る
const sum = (...numbers) => numbers.reduce((a, b) => a + b, 0);
console.log(sum(1, 2, 3, 4));

// 関数を引数に渡せる(これがコールバック)
const twice = (fn, value) => fn(fn(value));
console.log(twice(double, 5));

// 外側の変数を覚えたままの関数(クロージャ)
const makeCounter = () => {
  let count = 0;
  return () => ++count;
};
const next = makeCounter();
console.log(next(), next(), next());
function とアローの使い分け

迷ったらアロー関数で構いません。this の扱いが素直だからです。 function 宣言は「呼び出しより後ろに定義できる(巻き上げ)」ので、主役の処理を上に、部品を下に書きたいときに便利です。 オブジェクトのメソッドとして this を使いたいときは function(またはメソッド記法)を選びます。

09

クラス

「同じ形のデータ + それを扱う処理」をまとめる仕組みです。同じ種類のものをいくつも作るときに便利です。

JavaScript
class Cart {
  #items = [];                    // # で始まると外から触れない(プライベート)
  static taxRate = 0.1;           // クラス自体に属する値

  constructor(owner) {            // new したときに 1 度だけ走る
    this.owner = owner;
  }

  add(name, price) {              // メソッド
    this.#items.push({ name, price });
    return this;                  // this を返すと .add().add() とつなげられる
  }

  get count() {                   // ゲッター:() を付けずに読める
    return this.#items.length;
  }

  get total() {
    const sum = this.#items.reduce((a, item) => a + item.price, 0);
    return Math.round(sum * (1 + Cart.taxRate));
  }

  toString() {
    return `${this.owner}のカート:${this.count} 点 / ${this.total} 円`;
  }
}

const cart = new Cart('山田');
cart.add('えんぴつ', 120).add('ノート', 280);
console.log(cart.count, cart.total);
console.log(String(cart));

// 継承:元のクラスを受け継いで、一部だけ変える
class GiftCart extends Cart {
  get total() {
    return super.total + 300;     // 包装代を足す
  }
}

const gift = new GiftCart('鈴木');
gift.add('ノート', 280);
console.log(String(gift));

10

DOM 操作 — HTML を読み書きする

ブラウザは HTML を読み込むと、要素をたどれる木構造(DOM)に変換します。 JavaScript はこの木を探して・読んで・書き換えることでページを動かします。

下のデモは、この HTML に対して動いています。

HTML(デモの土台)
<h3 id="title">見出し</h3>
<p class="message">ここが書き換わります</p>
<ul id="list"></ul>
<button id="paint" type="button">色を変える</button>
JavaScript
// 1. 探す(CSS セレクタがそのまま使える)
const title = document.querySelector('#title');
const message = document.querySelector('.message');
const list = document.querySelector('#list');

// 2. 書き換える
title.textContent = 'JavaScript で書き換えた見出し';
message.textContent = `いまは ${new Date().toLocaleTimeString('ja-JP')} です`;

// 3. 作って足す
const fruits = ['りんご', 'みかん', 'ぶどう'];
for (const fruit of fruits) {
  const li = document.createElement('li');
  li.textContent = fruit;
  list.append(li);
}

// 4. クラスと属性
title.classList.add('is-active');
title.dataset.role = 'heading';        // data-role="heading" になる
title.style.color = '#2f80b8';         // 直接スタイルを当てることもできる

// 5. まとめて処理する
for (const li of document.querySelectorAll('#list li')) {
  li.style.fontWeight = '700';
}

// ボタンの動作は次の章で
document.querySelector('#paint').addEventListener('click', () => {
  message.style.backgroundColor = '#eaf2f8';
});

「色を変える」を押すと、実際に背景色が変わります。

querySelector()
条件に合う最初の 1 つ。無ければ null
querySelectorAll()
合うもの全部for...of で回せます。
textContent
文字を読み書きする。安全なのでまずこちら
innerHTML
HTML として解釈する。外部から来た文字を入れると危険(16 章参照)。
createElement / append
要素を作って、子として加える。
classList
add / remove / toggle / contains見た目の変更は CSS のクラス切り替えで
dataset
data-* 属性の読み書き。HTML 側に小さな情報を持たせられます。
closest()
自分から親をたどって、条件に合う祖先を探す。イベント処理で多用します。

11

イベント — 操作に反応する

「クリックされたら」「入力されたら」を addEventListener() で登録します。 HTML に onclick="…" と書く方法もありますが、 処理は JavaScript 側にまとめるのが今の作法です。

JavaScript
// クリック
const counter = document.querySelector('[data-count]');
let count = 0;

counter.addEventListener('click', () => {
  count += 1;
  counter.textContent = `押した回数:${count}`;
});

// 入力のたびに反応する
const who = document.querySelector('#who');
const hello = document.querySelector('.hello');

who.addEventListener('input', (event) => {
  const name = event.target.value.trim();
  hello.textContent = `こんにちは、${name || 'ゲスト'}さん`;
});

// イベント委譲:親で 1 つだけ受けて、どれが押されたかを調べる
// ボタンが増えても登録し直さなくてよい
document.querySelector('.menu').addEventListener('click', (event) => {
  const button = event.target.closest('button');
  if (!button) return;

  hello.style.color = button.dataset.color;
});
  • event.target … 実際に操作された要素。event.currentTarget は登録した側の要素です。
  • event.preventDefault() … 既定の動作(リンクの移動、フォーム送信)を止めます。
  • よく使うイベント:click input change submit keydown pointerdown scroll
  • スクロールなど大量に発火するイベントは、中で重い処理をしないこと。必要なら requestAnimationFrame で間引きます。

12

非同期処理 — 待つ処理の書き方

通信やタイマーは「すぐには終わらない処理」です。 JavaScript は待っている間も止まらずに次へ進むので、 終わったら何をするかを書いておく必要があります。それが Promiseasync / await です。

JavaScript
// 「あとで終わる処理」を作る
const wait = (ms, value) => new Promise((resolve) => setTimeout(() => resolve(value), ms));

console.log('1. ここが先に動く');

// async を付けた関数の中では await で「終わるまで待つ」と書ける
async function main() {
  const first = await wait(10, 'お茶');
  console.log('3. 届いた:', first);

  // 順番に待つ必要がないものは、まとめて待つほうが速い
  const [a, b] = await Promise.all([wait(10, 'パン'), wait(10, '牛乳')]);
  console.log('4. まとめて:', a, b);

  // 失敗するかもしれない処理は try / catch で囲む
  try {
    await Promise.reject(new Error('通信に失敗しました'));
  } catch (error) {
    console.log('5. 捕まえた:', error.message);
  }
}

main();
console.log('2. 待たずにここまで進む');

出力の順番に注目してください。1 → 2 → 3 → 4 → 5 の順で出ます。

JavaScript — サーバーからデータを取る
async function loadUsers() {
  try {
    const response = await fetch('/api/users.json');

    // fetch は 404 でも例外にならない。自分で確かめる
    if (!response.ok) throw new Error(`HTTP ${response.status}`);

    const users = await response.json();
    return users;
  } catch (error) {
    console.error('読み込みに失敗しました', error);
    return [];
  }
}
file:// では fetch が使えない

ファイルをダブルクリックして開いた状態(file://)では、セキュリティ上の制限で fetch や ES モジュールが動きません。試すときは、エディタの「ローカルサーバーで開く」機能を使うか、 npx serve のような簡易サーバーを立ててください。

13

モジュール — ファイルを分ける

コードが増えてきたら、役割ごとにファイルを分けます。 export で外に出し、import で取り込みます。

JavaScript
// ---- utils.js ----
export const tax = (price) => Math.round(price * 1.1);
export const format = (n) => `${n.toLocaleString()} 円`;

// ---- main.js ----
import { tax, format } from './utils.js';   // 拡張子まで書く
console.log(format(tax(1000)));

// HTML 側では type="module" を付ける
// <script type="module" src="main.js"></script>
  • type="module" を付けた <script>自動的に defer になり、中身は常に strict モードで動きます。
  • モジュールの中の変数はそのファイルだけのもの。名前の衝突を気にしなくて済みます。
  • ただし file:// では動きません(前章の注意と同じ理由)。小さなサイトなら、モジュールを使わず IIFE で包む書き方でも十分です。

14

最近入った便利な機能

JavaScript は毎年更新されています。ここ数年で入って、 もう普通に使えるものを挙げておきます。知っていると書く量がぐっと減ります。

JavaScript
const people = [
  { name: '山田', team: '営業' },
  { name: '鈴木', team: '開発' },
  { name: '佐藤', team: '営業' }
];

// Object.groupBy:キーごとにまとめる
console.log(Object.groupBy(people, (p) => p.team));

// 元を壊さない配列操作
const nums = [3, 1, 2];
console.log(nums.toSorted(), nums.toReversed(), nums.with(0, 99), nums);

// findLast / at
console.log(nums.findLast((n) => n < 3), nums.at(-1));

// Set の演算
const a = new Set([1, 2, 3]);
const b = new Set([2, 3, 4]);
console.log(a.union(b), a.intersection(b), a.difference(b));

// イテレータヘルパー:途中で打ち切れるので無駄がない
const evens = nums.values().filter((n) => n % 2 === 1).map((n) => n * 10).toArray();
console.log(evens);

// structuredClone:入れ子のオブジェクトも丸ごと複製
const original = { user: { name: '山田' } };
const copy = structuredClone(original);
copy.user.name = '別人';
console.log(original.user.name, copy.user.name);

// Promise.withResolvers:resolve / reject を外に取り出せる
const { promise, resolve } = Promise.withResolvers();
resolve('あとから解決できる');
promise.then((value) => console.log(value));
新しい機能を使うときは

言語仕様は毎年 6 月に更新され、ブラウザへの搭載はそれとは別のペースで進みます。 使う前に MDN の「ブラウザーの互換性」表か、Can I use で対応状況を確認してください。 using による自動後始末や、日付時刻を扱う Temporal のように、広まりつつある段階の機能もあります。

15

動かないときの調べ方

エラーは敵ではなく、ブラウザからの案内です。 まずコンソールを開く。話はそれからです。

よく出るエラーたいていの原因
Cannot read properties of null要素が見つかっていない。セレクタの綴り違い、または defer の付け忘れ
X is not defined変数名の打ち間違い、宣言し忘れ、スコープの外から使っている
X is not a functionメソッド名の間違い(querySelectorAllquerySelector と書いた等)
Unexpected token括弧や引用符の閉じ忘れ。エラーのすぐ上の行を疑う
何も起きないそもそも関数が呼ばれていない。console.log('ここ通った') を入れて確認
  1. コンソールを開く

    赤い文字を読む。ファイル名と行番号が書いてあります。

  2. console.log を挟む

    「どこまで動いたか」「変数に何が入っているか」を実際に見ます。

  3. 要素タブで DOM を見る

    思ったクラスが付いているか、CSS のどの行が効いているかが分かります。

  4. 小さく切り分ける

    怪しい部分だけを取り出して、単独で動かしてみます。

  5. それでも分からなければ検索

    エラーメッセージをそのまま貼って検索。MDN の解説が出てくれば当たりです。

16

モダンな Web 制作で知っておいてほしいこと

文法とは別に、作り方の姿勢の話です。最初にこれを知っておくと、あとで作り直す回数がかなり減ります。

  1. HTML → CSS → JavaScript の順で足す(段階的強化)

    まず HTML だけで内容が読める状態を作り、CSS で整え、最後に JavaScript で便利にします。 JS が読み込めなくてもページが死なない構造になり、表示も速くなります。 <details>:has() で済むことに JS を使わない、という判断もここに含まれます。

  2. デバイスの幅を決め打ちしない

    「iPhone は 390px だから」と個別対応を始めると終わりません。 内容が崩れる幅で切り替えるのが正解です。 clamp()auto-fill を使えば、そもそも切り替え自体が減ります。

  3. アクセシビリティは後付けできない

    正しいタグ、ラベル、代替テキスト、キーボード操作、コントラスト。どれも作り終わってから足すと大工事になります。 マウスを外して Tab キーだけで操作してみるのが、いちばん手軽な自己点検です。

  4. 表示速度は「画像」でほぼ決まる

    凝ったコードより、5MB の写真 1 枚のほうがずっと重いのが現実です。表示サイズの 2 倍までに縮める、width/height を書く、画面外は loading="lazy"。まずこの 3 つを守ってください。

  5. innerHTML に外から来た文字を入れない

    利用者の入力や URL の値をそのまま innerHTML に入れると、スクリプトを埋め込まれる恐れがあります(XSS)。 文字を入れるだけなら必ず textContent。外部サイトへのリンクには rel="noopener noreferrer" を付けます。

  6. フレームワークは急がなくてよい

    React や Vue は「状態が複雑なアプリ」のための道具です。数ページのサイトなら素の HTML/CSS/JS のほうが速くて壊れにくい。 土台が分かっていないと、フレームワークの不具合は直せません。

  7. ファイル構成と名前を決めておく

    assets/stylesheets/ assets/javascripts/ assets/images/ のように場所を決め、ファイル名は半角小文字とハイフンで。迷う時間が消え、他人(半年後の自分を含む)が読めるようになります。

  8. バージョン管理を最初から使う

    Git を入れて、区切りごとに記録(コミット)します。「昨日は動いていたのに」から復帰できるようになるだけで、挑戦できる幅が変わります。 GitHub に置けば、そのまま公開(GitHub Pages)もできます。

  9. ブラウザの開発者ツールを住処にする

    要素タブで DOM と CSS、コンソールでエラー、ネットワークで読み込み、 Lighthouse で速度とアクセシビリティの点検。 本を読むより、ここを触るほうが早く覚えます。

  10. 情報源を絞る

    仕様と使い方は MDN Web Docs、対応状況は Can I use。古い記事は「その時点の正解」でしかありません。 float で段組み、var、jQuery 前提の解説を見かけたら、まず年代を確認してください。

最後にひとつだけ

全部を覚えてから作り始める必要はありません。 小さくても、動くものを最後まで作るほうが、確実に身につきます。分からないことはそのつど調べればよく、そのために MDN があります。

17

次は Canvas へ

HTML で構造を、CSS で見た目を、JavaScript で動きを作れるようになりました。次は、絵そのものを JavaScript で描く世界です。ここまでの文法がそのまま道具になります。

STEP 4 / CANVAS ブラウザの中に絵を描く 座標・図形・文字・アニメーション・マウス操作を、動くデモ 16 本で。
その先の発展編では、時計・グラフ・お絵かきツール・15 パズルまで作ります。