document.currentScriptが想像以上に便利だった話

document.currentScriptが想像以上に便利だった話 プログラミング

JavaScriptを書いていて、「このスクリプトタグ自身を参照したい」と思ったことはありませんか?

私も最近まで知らなかったのですが、document.currentScriptという便利なプロパティがあります。
これを使うと、現在実行中のスクリプト要素への参照を簡単に取得できるんです。

今回は、このプロパティの基本的な使い方から、実践的な活用方法まで解説していきます。

document.currentScriptの基本

まず、基本的な使い方を見てみましょう。

<script id="my-script" data-message="こんにちは!">
  const script = document.currentScript;
  console.log(script.id); // "my-script"
  console.log(script.dataset.message); // "こんにちは!"
</script>

これだけです。
実行中のscriptタグへの参照が取得できました。

ただし、注意点があります。
このプロパティは同期的に実行されるスクリプト内でのみ有効です。

つまり、非同期処理の中ではnullになってしまいます。

// これは動作する
const script = document.currentScript;

// これは動作しない
setTimeout(() => {
  console.log(document.currentScript); // null
}, 100);

非同期処理で使いたい場合は、事前に変数に保存しておく必要があります。

バックエンドからデータを受け渡す

実は、document.currentScriptの真価は別のところにあります。
それは、バックエンドからフロントエンドへデータを渡すときです。

従来、サーバーサイドのデータをJavaScriptに渡すときは、グローバル変数を使うことが多かったと思います。

<!-- 従来の方法 -->
<script>
  window.CONFIG = {
    apiKey: 'abc123',
    userId: 456
  };
</script>
<script src="app.js"></script>

しかし、この方法にはいくつか問題があります。

グローバル変数の汚染。
CSP(Content Security Policy)での制限。
そして何より美しくない。

document.currentScriptを使えば、もっとエレガントに書けます。

<!-- data属性を使った方法 -->
<script 
  src="app.js"
  data-api-key="abc123"
  data-user-id="456">
</script>
// app.js
const config = {
  apiKey: document.currentScript.dataset.apiKey,
  userId: document.currentScript.dataset.userId
};

この方法の良いところは何でしょうか。
まず、CSPでインラインスクリプトが制限されていても問題なく動作します。

また、グローバル変数を使わないので、名前の衝突を心配する必要もありません。

サードパーティスクリプトでの活用

この手法が特に威力を発揮するのは、他のサイトに埋め込んでもらうスクリプトを作るときです。
例えば、チャットウィジェットのようなサービスを提供する場合を考えてみましょう。

<!-- 利用者のサイト -->
<script 
  src="https://example.com/chat-widget.js"
  data-client-id="customer123"
  data-theme="dark"
  data-position="bottom-right">
</script>
// chat-widget.js
(function() {
  const script = document.currentScript;
  const config = {
    clientId: script.dataset.clientId,
    theme: script.dataset.theme || 'light',
    position: script.dataset.position || 'bottom-right'
  };

  // ウィジェットの初期化処理
  initializeChatWidget(config);
})();

利用者は、scriptタグにdata属性を追加するだけで設定を変更できます。
JavaScriptのコードを書く必要はありません。

これは、技術的な知識が少ない人でも簡単に導入できるという大きなメリットです。

セキュリティ面でのメリット

document.currentScriptを使ったデータ受け渡しには、セキュリティ面でのメリットもあります。
インラインスクリプトでJSONデータを埋め込む場合を考えてみましょう。
XSS攻撃のリスクがあります。

<!-- 危険な例 -->
<script>
  const userData = <?php echo json_encode($userData); ?>;
</script>

もし$userDataに悪意のあるコードが含まれていたらどうなるでしょう。
大変なことになります。

一方、data属性を使う方法なら、HTMLエンコーディングが自動的に適用されます。
より安全です。

<!-- より安全な例 -->
<script 
  src="app.js"
  data-user='<?php echo htmlspecialchars(json_encode($userData)); ?>'>
</script>

実践的な使用例

最後に、実際のプロジェクトで使える例をいくつか紹介します。

Google Analytics風の実装

<script 
  src="/analytics.js"
  data-tracking-id="UA-12345-6"
  data-debug="true">
</script>
// analytics.js
(function() {
  const script = document.currentScript;
  const trackingId = script.dataset.trackingId;
  const debug = script.dataset.debug === 'true';

  if (!trackingId) {
    console.error('Tracking ID is required');
    return;
  }

  // 分析ライブラリの初期化
  initAnalytics(trackingId, { debug });
})();

動的なスタイル適用

<script 
  src="/theme-loader.js"
  data-primary-color="#007bff"
  data-font-size="16px">
</script>
// theme-loader.js
const script = document.currentScript;
const theme = {
  primaryColor: script.dataset.primaryColor || '#000',
  fontSize: script.dataset.fontSize || '14px'
};

// CSS変数として設定
const root = document.documentElement;
root.style.setProperty('--primary-color', theme.primaryColor);
root.style.setProperty('--font-size', theme.fontSize);

複数の設定をJSONで渡す

複雑な設定が必要な場合は、JSONを使うこともできます。

<script 
  src="/widget.js"
  data-config='{"api":"https://api.example.com","timeout":5000,"retry":3}'>
</script>
// widget.js
const script = document.currentScript;
const config = JSON.parse(script.dataset.config || '{}');

// デフォルト値とマージ
const finalConfig = {
  api: 'https://api.default.com',
  timeout: 3000,
  retry: 1,
  ...config
};

まとめ

document.currentScriptは、一見地味な機能に見えます。
でも、使い方次第でコードをよりクリーンに、より安全に書けるようになります。

特に以下のような場面で威力を発揮します:

  • サーバーサイドからクライアントサイドへのデータ受け渡し
  • サードパーティスクリプトの設定管理
  • CSP対応が必要な環境での実装
  • グローバル変数の汚染を避けたい場合

ただし、非同期処理での制限があることは忘れないでください。
必要に応じて変数に保存するなど、適切な対処が必要です。

この記事で紹介した手法を使えば、よりメンテナンスしやすく、セキュアなコードが書けるようになるはずです。
ぜひ実際のプロジェクトで試してみてください。

タイトルとURLをコピーしました