3

jsonPを使用してクロスドメイン情報を共有するスクリプトを使用しています。それはうまく機能しますが、私はそれをIIFEの中に入れる必要があります。

var domain = "http://example.com/";
var myObj = {
    recupData : function(data){
        if (data.id) {
            console.log(data.id);
        }
    },
    scriptTag : function() {
        var siteOrigin = domain+"check?q=myObj.recupData",
            script = document.createElement('script');
        script.type = 'text/javascript';
        script.async = true;
        script.src = siteOrigin;
        document.getElementsByTagName('HEAD')[0].appendChild(script);
    }
}
myObj.scriptTag();

それはうまくいきます!(構造を示すために、グローバルスクリプトのごく一部を取り上げただけなので、構文エラーが発生したとしても、それは重要ではありません)。

しかし、このコードを自己呼び出し関数であるIIFEに入れると、問題が発生します。

(function(){
var domain = "http://example.com/";
var myObj = {
    recupData : function(data){
        if (data.id) {
            console.log(data.id);
        }
    },
    scriptTag : function() {
        var siteOrigin = domain+"check?q=myObj.recupData",
            script = document.createElement('script');
        script.type = 'text/javascript';
        script.async = true;
        script.src = siteOrigin;
        document.getElementsByTagName('HEAD')[0].appendChild(script);
    }
}
myObj.scriptTag();
})();

myObjが定義されていないというエラーが表示されます。エラーは、scriptTagメソッドから発生します。IIFEを追加するまで、このメソッドにアクセスできない理由がよくわかりません。何も変更しないでください。グローバル名前空間を汚染します。文脈上の問​​題だと思いますが、説明が必要です。

4

1 に答える 1

4

IIFEを使用する動機は、変数名がグローバルスコープに「リーク」しないことです。ただし、JSONPを使用している場合は、ロードされたスクリプトがJSONP(またはそのメソッドの1つ)を呼び出せるように、少なくとも1つの変数をグローバルスコープに公開する必要があります。このロードされたスクリプトは、完全に異なるスコープで、に別個のscriptタグとして挿入されるheadため、グローバルスコープを介してのみ変数を共有できます。

たとえば、への呼び出しがhttp://mydomain.com/check?q=myObj.recupData次のような応答を生成するとします。

myObj.recupData({"id":123,"more":"stuff"})

これは、次のように記述したかのように、別のスクリプトタグ内に読み込まれます。

<script type="text/javascript">
myObj.recupData({"id":123,"more":"stuff"})
</script>

明らかに、この呼び出しが機能myObjする必要がある場合は、グローバルスコープ内にある必要があるため、その宣言をIIFEの外部に移動するか、windowオブジェクトに明示的に登録する必要があります。

// Global declaration
var myObj;
(function(){
    var domain = "http://mydomain.com/";
    myObj = { ... };
    myObj.scriptTag();
})();

// Registering on window
(function(){
    var domain = "http://mydomain.com/";
    // Also get it as a local variable
    // for a minor scope lookup optimization
    var myObj = window.myObj = { ... };
    myObj.scriptTag();
})();

2番目のオプションは、スニペットをどこに配置しても、常にグローバルスコープに含まれるため、より興味深い場合があります。何らかの理由で最初のスニペットを別のIIFE内にネストすることになった場合は、myObj宣言も移動することを忘れないでください。これは面倒な場合があります。

于 2013-01-30T14:10:33.843 に答える