2.

HTML に JavaScript を埋め込む完全ガイド

編集
この記事の要点
  • <script> タグでインライン記述、<script src> で外部ファイル読み込み
  • defer: HTML パース完了後・DOMContentLoaded 前に順次実行(推奨)
  • async: ダウンロード完了次第すぐ実行、順序保証なし(独立スクリプト向け)
  • type="module": ES Modules、import/export 使用可、自動で defer 相当
  • DOM 操作前には DOMContentLoaded イベントを待つ、innerHTML は XSS 対策必須

JavaScript を HTML に埋め込む 3 つの方法

1. インライン (script タグ内に直接記述)

<!DOCTYPE html>
<html>
<head>
    <title>Sample</title>
</head>
<body>
    <h1 id="title">Hello</h1>

    <script>
        // ここに JavaScript を直接書く
        document.getElementById('title').textContent = 'Hello, World!';
        console.log('inline script executed');
    </script>
</body>
</html>

2. 外部ファイル (推奨)

<!-- 同じディレクトリの app.js を読み込み -->
<script src="app.js"></script>

<!-- 絶対パス -->
<script src="/js/app.js"></script>

<!-- CDN -->
<script src="https://cdn.jsdelivr.net/npm/vue@3"></script>

<!-- 整合性ハッシュ + crossorigin(推奨セキュリティ設定) -->
<script
  src="https://cdn.example.com/lib.js"
  integrity="sha384-..."
  crossorigin="anonymous"></script>

3. インライン属性 (非推奨)

<!-- ❌ 非推奨(XSS リスク、CSP 違反、保守性低い) -->
<button onclick="alert('clicked')">Click</button>

<!-- ✅ addEventListener 推奨 -->
<button id="btn">Click</button>
<script>
  document.getElementById('btn').addEventListener('click', () => {
    alert('clicked');
  });
</script>

script タグの属性 (defer / async / type)

属性ダウンロード実行タイミング順序用途
なし同期、HTML パース停止即時HTML 内記述順互換性、最終手段
defer非同期HTML パース完了後、DOMContentLoaded 前HTML 内記述順★通常のアプリスクリプト
async非同期ダウンロード完了次第不定独立した解析タグ等
type="module"非同期defer 相当記述順ES Modules
<!DOCTYPE html>
<html>
<head>
    <!-- ★推奨: head に defer 付きで読み込み -->
    <script src="app.js" defer></script>

    <!-- 独立した広告/解析: async -->
    <script src="https://www.googletagmanager.com/gtag/js?id=GA_ID" async></script>

    <!-- ES Modules: 自動で defer 動作 -->
    <script src="main.js" type="module"></script>

    <!-- 旧ブラウザフォールバック: module 非対応で読まれる -->
    <script src="main-legacy.js" nomodule></script>
</head>
<body>
    <!-- body 末尾配置でも defer/async 不要だが、defer のほうが体感速い -->
</body>
</html>

ES Modules

<!-- index.html -->
<script type="module" src="main.js"></script>
// main.js
import { greet } from './utils.js';   // 拡張子必須
greet('World');

// utils.js
export function greet(name) {
  console.log(`Hello, ${name}`);
}

module は CORS / MIME (application/javascript) / 厳格モードが強制されるため、HTTP サーバ経由でアクセスする必要があります(file:// 直接開きは不可)。

DOM 操作の基本

<div id="app">Hello</div>
<ul class="list">
    <li>A</li>
    <li>B</li>
</ul>

<script>
// 要素取得
const app = document.getElementById('app');
const items = document.querySelectorAll('.list li');
const first = document.querySelector('.list li:first-child');

// テキスト書き換え
app.textContent = 'World';

// HTML として埋め込み(XSS 注意)
app.innerHTML = '<strong>Bold</strong>';

// 属性
app.setAttribute('data-id', '42');
app.dataset.id = '42';

// クラス
app.classList.add('active');
app.classList.toggle('hidden');

// スタイル
app.style.color = 'red';

// イベント
app.addEventListener('click', (e) => {
  console.log('clicked', e.target);
});

// 子要素追加
const li = document.createElement('li');
li.textContent = 'C';
document.querySelector('.list').appendChild(li);
</script>

innerText / textContent / innerHTML の違い

プロパティHTML タグ非表示要素パフォーマンスXSS
textContent取得・設定とも文字列扱い(エスケープ済)含む★高速安全
innerText表示テキストのみ含まない遅い(レイアウト必要)安全
innerHTMLHTML として解釈含む遅い(パース必要)★危険

XSS (クロスサイトスクリプティング) 対策

// ❌ 危険: ユーザー入力を innerHTML に直接
const userInput = '';
element.innerHTML = userInput;    // → スクリプト実行される

// ✅ textContent で文字列扱い
element.textContent = userInput;  // → ""']/g, m => ({
    '&': '&', '<': '<', '>': '>', '"': '"', "'": '''
  }[m]));
}
element.innerHTML = escapeHtml(userInput);

DOMContentLoaded と load イベント

イベント発火タイミング用途
DOMContentLoadedHTML パース + defer スクリプト完了時★ DOM 操作開始
load画像/CSS/iframe 含め全リソース完了サイズ計算等、画像確認
document.addEventListener('DOMContentLoaded', () => {
  // ここから安全に DOM 操作可能
  init();
});

window.addEventListener('load', () => {
  // 画像 size などの最終確認
});

// 既に発火済みかチェック
if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', init);
} else {
  init();   // 既に発火後なら即実行
}

FAQ

Q: defer と body 末尾配置、どちらが良い?
A: 機能的にはほぼ同じですが、defer + head 配置のほうが「ダウンロードが HTML パースと並行して始まる」ぶん体感が速くなります。

Q: document.write は?
A: 非推奨。HTML パース後に呼ぶとページ全体を破壊します。広告タグ等の互換目的以外は使わないこと。

Q: jQuery の $(function(){})DOMContentLoaded の違いは?
A: 同じです。jQuery 内部でも DOMContentLoaded を待つ実装になっています。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 基本事項
  2. HTMLへの埋め込み
  3. 変数
  4. 可変変数
  5. 定数
  6. データ型
  7. キャスト
  8. エスケープ文字
  9. 配列
  10. 演算子
  11. 代入の際の注意点
  12. 条件分岐
  13. 繰り返し処理
  14. クラスとインスタンス
  15. コンストラクタ
  16. 関数
  17. スーパーグローバル変数
  18. スコープ
  19. staticについて
  20. yieldについて
  21. ファイルのアップロード方法
  22. DB接続方法
  23. SQL実行方法
  24. カプセル化の具体例
  25. 継承の構文
  26. オーバーライド
  27. ポリモーフィズム(多様性)の具体例
  28. 抽象クラス・メソッドの構文と具体例
  29. GET通信
  30. try catchで全てのエラーを拾う方法

最近更新/作成されたページ