外部JavaScript本人の<script>要素を取得方法を考える

はじめに

外部JavaScript本人の<script>要素を取得方法として、標準で

document.currentScript

が提供されていますが、各ブラウザの対応状況は
こんな
スクリーンショット 2018-03-15 23.28.48.png
感じとなっております。

そう。またIEなんだ。

もうしばらくしたら、無視できるかもしれませんが今はまだIE対応が必要です……(よね?)

とりあえずググる

ちょっとググると、

こんな感じで見つかります。

どれもこれもまとめると、

index.html
<!DOCTYPE html>
<html>

<body>
    <script src="//code.jquery.com/jquery-3.3.1.min.js"></script>
    <script src="hoge.js"></script>
</body>

</html>
hoge.js
(function() {
    var currentScript = (function() {
        if (document.currentScript) {

            return document.currentScript;
        }

        var scripts = document.getElementsByTagName('script');

        return scripts[scripts.length - 1];
    })();

    console.log(currentScript);

})();

こうしろってこと。

通常の場合、<script>タグはレンダリングブロックしますので、その時点での最後の<script>タグを取得すれば、自分自身となる……
というわけですね。

でもこれ、バグるので気をつけてください。

バグる例

まず、レンダリングブロックされることを期待した処理となりますので、
 deferやasyncでhoge.jsを呼び出すと、期待する動作にならないことがあります。

また、動的にスクリプトタグを書き出す処理がある場合も、問題を起こします。

index.html
<!DOCTYPE html>
<html>
<body>
        <script>
            (function () {
                var script = document.createElement('script');
                script.src = "//code.jquery.com/jquery-3.3.1.min.js";
                document.body.appendChild(script);
            })();
        </script>
        <script src="hoge.js"></script>
</body>
</html>

こんな感じでJSで動的にスクリプトタグを取得したい<script>タグ(今回の場合は<script src="hoge.js"></script>)よりあとに挿入すると、hoge.jsで取得するのは、jQueryの呼び出し部分となります。

昨今では、タグマネージャーなどを使って動的にスクリプトタグが書き出される機会が増えていますので、動的にスクリプトタグを書き出す処理なんてないから、安心安全!とはなりません。

残念ながら。

ようやく本題「外部JavaScript本人の<script>要素を取得方法を考える。」ただし、document.currentScriptは除く

『srcの中身を指定するよ』派

hoge.js
(function() {
    var currentScript = (function() {
        if (document.currentScript) {

            return document.currentScript;
        }

        return document.querySelector('script[src="foo.js"]');
    })();

    console.log(currentScript);

})();

srcの中身が決まっているなら、これが一番手っ取り早いかもしれませんね。

ただ、以下のような場合、バグるので気をつけてください。

index.html
<!DOCTYPE html>
<html>
<body>
    <script src="hoge.js"></script>
    <script src="hoge.js"></script>
</body>
</html>

同じsrcが指定されたJSが二回呼ばれた場合、
 『自分自身の<script>要素を取得する』という目的は果たせないものとなります。

また、

  • CDNを使ってるいなどの理由で、開発と本番でドメインが違う
  • CDNを使っているなどの理由で、クエリパラメータを動的に付加している

などといった場合非常に面倒です。

以下で紹介する、idやdataと違ってかぶりにくいと言うのはありますが。

『idをつけるよ』派

index.html
<!DOCTYPE html>
<html>
<body>
     <script src="hoge.js" id="js-hoge"></script>
</body>
</html>
hoge.js
(function() {
    var currentScript = (function() {
        if (document.currentScript) {

            return document.currentScript;
        }

        return document.getElementById('js-hoge');
    })();

    console.log(currentScript);

})();

HTMLの制約が守られているなら、idはユニークになりますので、これなら大丈夫ですが、

  • 第三者に提供するなら、絶対にかぶらないIDにする必要がある
  • やはり、同じスクリプトタグを複数回使用することはできない

と言った問題があります。

『dataを指定するよ』派

index.html
<!DOCTYPE html>
<html>
<body>
    <script src="hoge.js" data-hoge="js-hoge"></script>
</body>
</html>
hoge.js
(function() {
    var currentScript = (function() {
        if (document.currentScript) {

            return document.currentScript;
        }

        return document.querySelector('script[data-hoge="js-hoge"]');

    })();

    console.log(currentScript);

})();
  • data-***部分と、その値がかぶらない限りは大丈夫。
  • やはり、同じスクリプトタグを複数回使用することはできない。

正直「ID指定とどう違うのか?」と問われると微妙な感じがしますね。
優位性はあまりないです。

他にも、classを指定する事も考えましたが、同じく優位性がないのでやめました。まだ、dataのがマシかなー

『onloadを使うよ』派

グローバルに変数を定義できるなら、以下の方法がシンプルです。

index.html
<!DOCTYPE html>
<html>
<body>
    <script src="hoge.js" onload="hoge(this);"></script>
</body>
</html>
hoge.js
var hoge = function (currentScript) {
    console.log(currentScript);
};

 - 複数箇所で呼び出しても正しく動作する
 - グローバルが汚れる
 - 定義されている変数がかぶると大惨事

さいごに

結局、これだ!って方法がないことがわかった。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.