在 Javascript 中使用 IIFE 的作用域

问题描述 投票:0回答:2

我正在使用一个使用 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 is not defined,错误来自 scriptTag 方法,我真的不明白为什么在添加 IIFE 之前我无法访问此方法,它不应该改变任何东西,它只是避免污染全局命名空间。 我认为这只是一个上下文问题,但我需要一个解释。

javascript namespaces scope iife
2个回答
4
投票

使用 IIFE 的动机是你的变量名不会“泄漏”到全局范围内。但是,当您使用 JSONP 时,您有义务将至少一个变量暴露给全局范围,以便加载的脚本可以调用它(或其方法之一)。这个加载的脚本作为一个单独的

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();
})();

第二个选项可能更有趣,因为它总是在全局范围内结束,无论您将代码段放在何处。如果由于某种原因你最终将第一个代码片段嵌套在另一个 IIFE 中,你还需要记住移动

myObj
声明,这可能很麻烦。


0
投票

也许你只是使用带参数的 iifee 函数,最后将它分配给 windows 范围,就像这个例子:

(function(obj){
    var domain = "http://example.com/";
    obj.scriptTag = () => {console.log(domain)};
   })(window.myObj = {});
   
   console.log(myObj.scriptTag());

像对象一样传递 myObj,然后通过引用传递给 iife 函数。您可以使用 this.myObj 将 obj 结果存储在 repective 域中。

© www.soinside.com 2019 - 2024. All rights reserved.