| この記事の要点 |
|
HTML への書き方
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<script src="/js/app.js" defer></script>
</head>
<body>
<button id="btn">押す</button>
<script>
document.getElementById("btn").addEventListener("click", () => {
console.log("押された");
});
</script>
</body>
</html>
| 書き方 | 読み込み | 実行タイミング | 順序 |
|---|---|---|---|
<script src> | その場で止まる | すぐ | 書いた順 |
defer | 並行 | HTML の解析後 | 書いた順 |
async | 並行 | 読み込めた瞬間 | 不定 |
type="module" | 並行 | HTML の解析後(defer と同じ) | 書いた順 |
迷ったら defer です。async は他のスクリプトに依存しない計測タグなどに限ります。</body> の直前に置く方法も動きますが、defer なら <head> に置けて読み込みが早く始まります。
要素が見つからないときの原因
<head>
<script>
// defer が無いのでこの時点ではまだ button が存在しない
document.getElementById("btn").addEventListener("click", f);
// Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')
</script>
</head>
// 対処 1: defer を付ける(推奨)
// 対処 2: DOM の構築完了を待つ
document.addEventListener("DOMContentLoaded", () => {
document.getElementById("btn").addEventListener("click", f);
});
詳細は Cannot read properties of null (reading 'addEventListener') を参照してください。
モジュールとして書く
// utils.js
export function taxIncluded(price, rate = 0.1) {
return Math.floor(price * (1 + rate));
}
export const TAX_RATE = 0.1;
export default function main() { /* ... */ }
// app.js
import main, { taxIncluded, TAX_RATE } from "./utils.js";
console.log(taxIncluded(1000)); // 1100
<script type="module" src="/js/app.js"></script>
モジュールには次の性質があります。
- 自動的に strict モードになる(
"use strict"を書かなくてよい) - トップレベルの変数が
windowに漏れない file://で開くと CORS に阻まれる。ローカルでも HTTP サーバーが要る- 相対パスの拡張子(
.js)を省略できない
セミコロンと自動挿入
// 行頭が ( や [ だと前の行と繋がる
const a = 1
const b = a
[1, 2].forEach(n => console.log(n))
// → const b = a[1, 2].forEach(...) と解釈されてエラー
// return の後ろで改行すると undefined が返る
function bad() {
return
{ ok: true }; // ← ここには到達しない
}
console.log(bad()); // undefined
function good() {
return { // 波かっこは同じ行に置く
ok: true,
};
}
セミコロンを付けない流儀もありますが、その場合は行頭の ( [ ` に注意が要ります。Prettier に任せれば自動でそろうので、書き方を統一して機械に任せるのが確実です。
変数と関数の書き方
const MAX_RETRY = 3; // 定数は UPPER_SNAKE
let count = 0; // 再代入するものだけ let
const userName = "田中"; // 変数・関数は camelCase
class UserProfile {} // クラスは PascalCase
const _internal = 1; // 内部用は先頭アンダースコア(慣習)
function calcTotal(items) {} // 関数宣言
const calcTotal = (items) => {}; // アロー関数
// 文字列はテンプレートリテラルで組み立てる
console.log(`合計 ${count} 件`);
strict モード
"use strict"; // ファイルの先頭(モジュールでは不要)
x = 1; // ReferenceError: x is not defined
// strict でなければ暗黙のグローバル変数が作られてしまう
function f() {
console.log(this); // strict では undefined、非 strict では window
}
宣言し忘れた変数がグローバルに漏れる事故を防げます。モジュールとクラスの中は自動的に strict なので、明示的に書く場面は減っています。
整形と検査
npm install -D prettier eslint
npx prettier --write . # 整形(インデント・クォート・セミコロン)
npx eslint . # 未使用変数・未定義変数などを検出
npx eslint . --fix # 直せるものは自動修正
Prettier は見た目、ESLint は間違いやすい書き方を担当します。役割が違うので両方入れます。
console でのデバッグ
const user = { name: "田中", age: 30 };
console.log(user);
console.log({ user }); // 変数名も一緒に表示される
console.table([user, user]); // 配列やオブジェクトの一覧を表で
console.dir(document.body); // DOM をオブジェクトとして展開
console.time("処理"); /* ... */ console.timeEnd("処理");
console.trace(); // ここまでの呼び出し経路
console.log({ user }) と波かっこで囲むと、変数名がラベルとして付いて出力されます。複数の値を出すときに取り違えません。
文字列はテンプレートリテラルで組み立てる
const name = "田中";
const count = 3;
// バッククォートで囲むと ${} で式を埋め込める
console.log(`${name} さんの件数は ${count} 件`);
console.log(`税込 ${Math.floor(1000 * 1.1)} 円`);
// 改行をそのまま書ける
const html = `
<ul>
<li>${name}</li>
</ul>
`;
// クォートの中の同じ記号だけエスケープが要る
const a = "彼は \"はい\" と答えた";
const b = '彼は "はい" と答えた'; // 囲みを変えればエスケープ不要
const c = `彼は "はい" と答えた`;
テンプレートリテラルに利用者の入力をそのまま入れて innerHTML に代入しないでください。HTML として解釈され XSS になります。文字を表示するだけなら textContent を使います。
文と式
// 式(値になるもの)
1 + 2
name === "田中"
cond ? "A" : "B"
items.map((n) => n * 2)
// 文(値にならないもの)
if (cond) { }
for (const x of xs) { }
return value;
// 式が必要な場所に文は書けない
// const x = if (cond) { 1 } else { 2 }; // SyntaxError
const x = cond ? 1 : 2; // 三項演算子を使う
// 波かっこはブロックにもオブジェクトにもなる
{ a: 1 } // 文の位置ではブロック(ラベル a)として解釈される
const o = { a: 1 }; // 代入の右辺ならオブジェクト
(() => ({ a: 1 }))(); // アローで返すときは丸かっこで囲む
エラーを握りつぶさない
// 悪い例: 何が起きたか分からなくなる
try {
doSomething();
} catch (e) {
// 何も書かない
}
// 良い例: 記録して、対処できないなら投げ直す
try {
doSomething();
} catch (e) {
console.error("処理に失敗しました", e);
throw e;
}
// catch の引数は省略できる(値を使わないとき)
try { risky(); } catch { fallback(); }
// 非同期は await を try で囲む
try {
const res = await fetch("/api");
if (!res.ok) throw new Error(`HTTP ${res.status}`);
} catch (e) {
console.error(e);
}
fetch() は 404 や 500 でも例外になりません。通信自体が失敗したときだけ reject するので、ステータスは res.ok で確認してください。
グローバルを汚さない
// 通常のスクリプト: トップレベルの const/let も他ファイルから見える
// (var と function は window にも生える)
var config = {}; // window.config になる
// モジュール: ファイルの中に閉じる
export const config = {}; // 明示的に export したものだけ他から使える
複数の <script> を読み込むページでは、同じ名前の const を 2 つ宣言すると SyntaxError: Identifier 'x' has already been declared になります。type="module" にすればファイルごとに閉じるので、この衝突が起きません。
よくあるつまずき
| 症状 | 原因 |
|---|---|
| スクリプトが動かない | 読み込み失敗。開発者ツールの Network タブで 404 を確認する |
Cannot read properties of null | DOM 構築前に実行している。defer を付ける |
Unexpected token '<' | JS ファイルのつもりで HTML(404 ページ)を読んでいる |
import が使えない | type="module" が無い/ファイルを直接開いている |
| 変更が反映されない | ブラウザキャッシュ。強制リロードするか URL にバージョンを付ける |
| 日本語が化ける | <meta charset="utf-8"> と実ファイルの文字コードを UTF-8 にそろえる |
関連
子ページはありません
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- Git pushした変更の取消し|revert・履歴変更と保護の注意点 2026-10-15 23:49:01
- Gitでローカルを戻す前に|reset・restoreの違いと退避範囲 2026-10-15 23:49:01
- Git rebaseの使い方|対象範囲・競合解決・pushの判断 2026-10-15 22:50:59
- Git pullの使い方|取込み先・ff-only・競合とstashの注意点 2026-10-15 22:50:59
- Git pushの使い方|送信先・タグ・force-with-leaseの条件 2026-10-15 22:12:47
- Git remoteの設定・確認・削除|SSH URLとfetch/pushの違い 2026-10-15 22:12:47
- Gitリモートリポジトリの作成|初回push・既存履歴・mirrorの注意 2026-10-15 15:48:16
- Gitのuser.name・user.email設定|local/global・確認と過去履歴の注意 2026-10-15 15:30:07
- LinuxにGitをインストール|配布元・初期設定・TLSと認証の確認 2026-10-15 15:30:06
- Git導入と初回push|Linuxサーバー・Windows/macOS・SSH設定 2026-10-15 14:51:54
- Db2のCREATE INDEX|索引定義・INCLUDEと実行計画の確認 2026-10-15 14:10:22
- Db2の自動採番|IDENTITY・ID取得とRESTARTの注意点 2026-10-15 14:10:22
- 【DB2】特定スキーマの全テーブルの全カラム情報を取得する方法 2026-10-15 13:53:15
- Db2のシーケンスとIDENTITYの違い|採番とカタログの確認SQL 2026-10-15 13:53:15
- Db2で複数カラムをUPDATEする方法|SET・WHEREと更新前の値 2026-10-15 13:53:15