この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:6
ページ更新者:guest
更新日時:2026-06-11 07:07:02

タイトル: HTMLへの埋め込み
SEOタイトル: HTML に JavaScript を埋め込む完全ガイド

この本文には実行可能なタグ等が含まれるため、安全のためHTMLソースとして表示しています。本文データは変更していません。

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;background:#fffbea;border:1px solid #f4c430;margin:1em 0;width:100%"><tr><td style="background:#f4c430;color:#000;font-weight:bold;padding:8px">この記事の要点</td></tr><tr><td style="padding:10px"><ul><li><strong><script></strong> タグでインライン記述、<strong><script src></strong> で外部ファイル読み込み</li><li><strong>defer</strong>: HTML パース完了後・DOMContentLoaded 前に順次実行(推奨)</li><li><strong>async</strong>: ダウンロード完了次第すぐ実行、順序保証なし(独立スクリプト向け)</li><li><strong>type="module"</strong>: ES Modules、<code>import/export</code> 使用可、自動で defer 相当</li><li>DOM 操作前には <strong>DOMContentLoaded</strong> イベントを待つ、innerHTML は XSS 対策必須</li></ul></td></tr></table>
<h2>JavaScript を HTML に埋め込む 3 つの方法</h2>

<h3>1. インライン (script タグ内に直接記述)</h3>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><!DOCTYPE html>
<html>
<head>
    <title>Sample</title>
</head>
<body>
    <h1 id="title">Hello</h1>

    <script>
        // ここに JavaScript を直接書く
        document.getElementById(&apos;title&apos;).textContent = &apos;Hello, World!&apos;;
        console.log(&apos;inline script executed&apos;);
    </script>
</body>
</html></code></pre>
<h3>2. 外部ファイル (推奨)</h3>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><!-- 同じディレクトリの 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></code></pre>
<h3>3. インライン属性 (非推奨)</h3>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><!-- ❌ 非推奨(XSS リスク、CSP 違反、保守性低い) -->
<button onclick="alert(&apos;clicked&apos;)">Click</button>

<!-- ✅ addEventListener 推奨 -->
<button id="btn">Click</button>
<script>
  document.getElementById(&apos;btn&apos;).addEventListener(&apos;click&apos;, () => {
    alert(&apos;clicked&apos;);
  });
</script></code></pre>
<h2>script タグの属性 (defer / async / type)</h2>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>属性</th><th>ダウンロード</th><th>実行タイミング</th><th>順序</th><th>用途</th></tr></thead>
<tbody>
<tr><td>なし</td><td>同期、HTML パース停止</td><td>即時</td><td>HTML 内記述順</td><td>互換性、最終手段</td></tr>
<tr><td><code>defer</code></td><td>非同期</td><td>HTML パース完了後、DOMContentLoaded 前</td><td>HTML 内記述順</td><td>★通常のアプリスクリプト</td></tr>
<tr><td><code>async</code></td><td>非同期</td><td>ダウンロード完了次第</td><td>不定</td><td>独立した解析タグ等</td></tr>
<tr><td><code>type="module"</code></td><td>非同期</td><td>defer 相当</td><td>記述順</td><td>ES Modules</td></tr>
</tbody>
</table>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><!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></code></pre>
<h2>ES Modules</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><!-- index.html -->
<script type="module" src="main.js"></script></code></pre><pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">// main.js
import { greet } from &apos;./utils.js&apos;;   // 拡張子必須
greet(&apos;World&apos;);

// utils.js
export function greet(name) {
  console.log(`Hello, ${name}`);
}</code></pre>
<p>module は CORS / MIME (<code>application/javascript</code>) / 厳格モードが強制されるため、HTTP サーバ経由でアクセスする必要があります(<code>file://</code> 直接開きは不可)。</p>

<h2>DOM 操作の基本</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><div id="app">Hello</div>
<ul class="list">
    <li>A</li>
    <li>B</li>
</ul>

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

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

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

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

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

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

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

// 子要素追加
const li = document.createElement(&apos;li&apos;);
li.textContent = &apos;C&apos;;
document.querySelector(&apos;.list&apos;).appendChild(li);
</script></code></pre>
<h2>innerText / textContent / innerHTML の違い</h2>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>プロパティ</th><th>HTML タグ</th><th>非表示要素</th><th>パフォーマンス</th><th>XSS</th></tr></thead>
<tbody>
<tr><td><code>textContent</code></td><td>取得・設定とも文字列扱い(エスケープ済)</td><td>含む</td><td>★高速</td><td>安全</td></tr>
<tr><td><code>innerText</code></td><td>表示テキストのみ</td><td>含まない</td><td>遅い(レイアウト必要)</td><td>安全</td></tr>
<tr><td><code>innerHTML</code></td><td>HTML として解釈</td><td>含む</td><td>遅い(パース必要)</td><td>★危険</td></tr>
</tbody>
</table>

<h2>XSS (クロスサイトスクリプティング) 対策</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">// ❌ 危険: ユーザー入力を innerHTML に直接
const userInput = &apos;<img src=x onerror="alert(1)">&apos;;
element.innerHTML = userInput;    // → スクリプト実行される

// ✅ textContent で文字列扱い
element.textContent = userInput;  // → "<img src=x..." と文字列表示

// ✅ どうしても HTML として描画したい場合は DOMPurify でサニタイズ
import DOMPurify from &apos;dompurify&apos;;
element.innerHTML = DOMPurify.sanitize(userInput);

// ✅ 自前エスケープ関数(簡易)
function escapeHtml(str) {
  return str.replace(/[&<>"&apos;]/g, m => ({
    &apos;&&apos;: &apos;&amp;&apos;, &apos;<&apos;: &apos;&lt;&apos;, &apos;>&apos;: &apos;&gt;&apos;, &apos;"&apos;: &apos;&quot;&apos;, "&apos;": &apos;&#39;&apos;
  }[m]));
}
element.innerHTML = escapeHtml(userInput);</code></pre>
<h2>DOMContentLoaded と load イベント</h2>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>イベント</th><th>発火タイミング</th><th>用途</th></tr></thead>
<tbody>
<tr><td><code>DOMContentLoaded</code></td><td>HTML パース + defer スクリプト完了時</td><td>★ DOM 操作開始</td></tr>
<tr><td><code>load</code></td><td>画像/CSS/iframe 含め全リソース完了</td><td>サイズ計算等、画像確認</td></tr>
</tbody>
</table>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">document.addEventListener(&apos;DOMContentLoaded&apos;, () => {
  // ここから安全に DOM 操作可能
  init();
});

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

// 既に発火済みかチェック
if (document.readyState === &apos;loading&apos;) {
  document.addEventListener(&apos;DOMContentLoaded&apos;, init);
} else {
  init();   // 既に発火後なら即実行
}</code></pre>
<h2>FAQ</h2>

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

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

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