最後のscript tagの取得方法

ブログパーツを作成する場合自身のscript tagを取得したい場合が多く、そのときの手法としては次の手法が使われることが多いと思います。IT戦記 とてもシンプルに自分自身が属する script 要素を取得

ただ、この手法は読み込んでいる別script内でappendChildしていると、自身のscript tagがうまく取得できない場合があるようです。

サンプル(IE7,FF2,safari3.1で動作確認)

コードとしては単純に末尾のscript tagを取得しているだけですが、本来出力されるべき「second_script」ではなく、一つ前のscript内で追加している「append_script」が出力されてしまっています。

ここではコードを単純にするためsetTimeoutで検証していますが、XHR(XMLHttpRequest)やwindow.onload等の処理の流れを変えるようなfunctionでも同様の影響があるようです(ただ、検証した範囲ではwindow.onloadでは再現しませんでした)


//index.html内でとして読み込んでいるscript
setTimeout(function () {
    var scp = document.createElement('script');
    scp.id = 'append_script';
    document.body.appendChild(scp);
}, 0);

//index.html内でとして読み込んでいるscript
new function () {
    var currentScript = (function (e) { if(e.nodeName.toLowerCase() == 'script') return e; return arguments.callee(e.lastChild) })(document);
    document.write(currentScript.id);
}

解決方法としては以下のようにdocument.getElementsByTagName('script')で取得した中から、src等を見て解決するのがよさそうです。


new function () {
    var currentScript = (function (tags) {
        var i = tags.length;
        while (i--) {
            if (!tags[i].src) continue;
            if (!tags[i].src.match(/second_script\.js/)) continue;
            return tags[i];
        }
    })(document.getElementsByTagName('script'));
    document.write(currentScript.id);
}

2008/07/15 はてなブックマーク経由でコメントいただいたんですが、確実に「append_script」が表示されるわけでもなさそうです(手元の環境でもリロードすると「second_script」が表示されることもありました)。表示される結果はタイミング依存するようです。