Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/424.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何为每个JS文件使用闭包,但仍然让文件相互交互。_Javascript_Closures_Iife - Fatal编程技术网

Javascript 如何为每个JS文件使用闭包,但仍然让文件相互交互。

Javascript 如何为每个JS文件使用闭包,但仍然让文件相互交互。,javascript,closures,iife,Javascript,Closures,Iife,我知道使用闭包(IIFE)是最佳实践,因为它可以防止污染全局名称空间。但是,当我将闭包添加到文件中时,它阻止了我的第二个文件(controllers.js)读取第一个文件(models.js)。给你一个想法,下面是它们的样子: models.js ;(function() { function searchResult (obj) { this.state = obj.State; /*Do more stuff */ } })(); ;(function() {

我知道使用闭包(IIFE)是最佳实践,因为它可以防止污染全局名称空间。但是,当我将闭包添加到文件中时,它阻止了我的第二个文件(controllers.js)读取第一个文件(models.js)。给你一个想法,下面是它们的样子:

models.js

;(function() {
  function searchResult (obj) {
    this.state = obj.State;
    /*Do more stuff */
  }

})();
;(function() {
 function storeSearchResults(jsonObj) {
   var instance = new searchResult(jsonObj.data[i]);
   /* Do more */
 }     
})();
controllers.js

;(function() {
  function searchResult (obj) {
    this.state = obj.State;
    /*Do more stuff */
  }

})();
;(function() {
 function storeSearchResults(jsonObj) {
   var instance = new searchResult(jsonObj.data[i]);
   /* Do more */
 }     
})();
现在我已经在它们上添加了闭包,我得到了一个错误,
searchResult
在controllers.js中没有定义——因为它看不到它存在于models.js中。如何让它理解它存在于另一个文件中


是的,models.js是在controllers.js文件之前添加到HTML文件中的。

要让它们进行交互,它们必须有一些公共符号。您有两个选择:

  • 自己动手(使用单个全局变量)

  • 使用某种类型的库(理想情况下只使用一个全局符号)

  • 用一种完全不需要全球通用符号的不同方式自己动手

  • 自己动手 DIY版本通常是,对于整个应用程序,您有一个单一的全局应用程序,您的各个模块将属性添加到其中

    例如:

    models.js:

    ;(function(globals) {
      var MyApp = globals.MyApp = globals.MyApp || {};
      MyApp.searchResult = searchResult;
      function searchResult (obj) {
        this.state = obj.State;
        /*Do more stuff */
      }
    
    })(this);
    
    这是因为在松散模式下,
    全局范围内的这个
    是全局对象(
    浏览器上的窗口
    )。我们将其作为参数
    globals
    传递到IIFE中,然后在其上使用或创建名为
    MyApp
    的属性,并将
    searchResult
    作为属性添加到其中

    controllers.js:

    ;(function(globals) {
      var MyApp = globals.MyApp = globals.MyApp || {};
      function storeSearchResults(jsonObj) {
        var instance = new MyApp.searchResult(jsonObj.data[i]);
        /* Do more */
     }     
    })(this);
    
    ;
    function storeSearchResults(jsonObj) {
      var instance = new searchResult(jsonObj.data[i]);
      /* Do more */
    }
    
    我们做了同样的事情,只是
    controllers.js
    希望
    models.js
    已经运行。尽管我们仍然执行
    var MyApp=globals.MyApp=globals.MyApp | |{}models.js
    ,那么
    新的MyApp.searchResult
    当然会失败

    这个主题可能有十几种语法变体,这只是其中之一

    使用某种能为你做这件事的图书馆 您的另一个选择是使用库(其中的一个全局符号是
    require
    ,它是一个函数)或任何其他库

    你自己用另一种方式做 另一个DIY选项完全摆脱了全局,你甚至不需要一个全局

    要做到这一点,您的单个文件没有iLife(尽管它们可以将iLife用于不想与其他文件共享的内容):

    controllers.js:

    ;(function(globals) {
      var MyApp = globals.MyApp = globals.MyApp || {};
      function storeSearchResults(jsonObj) {
        var instance = new MyApp.searchResult(jsonObj.data[i]);
        /* Do more */
     }     
    })(this);
    
    ;
    function storeSearchResults(jsonObj) {
      var instance = new searchResult(jsonObj.data[i]);
      /* Do more */
    }
    
    然后你用一个缩微器把你的脚本组合起来,并把它们包装成一个大生命。您可能有
    pre.js

    (function() {
    
    })();
    
    post.js

    (function() {
    
    })();
    
    然后minifier通过组合
    pre.js+models.js+controllers.js+post.js
    创建
    app.js
    。最终结果(为便于阅读,此处未缩小并格式化)为:


    我称之为DIY,但如果有工具可以帮助我,我不会感到惊讶。

    事件和侦听器传递和接收数据

    我不使用globals


    然而,我不知道如何在原始javascript中使用事件,或者是否可以完成数据传递。我使用jquery/node,它允许传递数据,而且工作非常出色。

    您可以使用模块系统,如(AMD)或(CommonJS)。谢谢@TJ,您解决了我的问题!为了理解,我有两个问题:1)每个生命结束时的
    (这个)
    参数是为了什么?2.
    controllers.js
    如何理解从何处获取
    全局
    参数——因为没有人显式调用它?@ayjay:在
    脚本
    块的顶层,如果您没有使用
    “use strict”
    这是全局对象(浏览器上称为
    window
    ;从技术上讲,
    window
    是全局对象的一个属性,它是一个全局变量,用于引用自身)。因此,通过将
    这个
    传递到我们的IIFE中,我们可以用参数名
    全局
    引用它(我通常使用
    “use strict”
    在iLife的顶部,因此函数中的代码是严格模式,因为严格模式非常方便。但是在iLife之外,我喜欢使用
    这个
    窗口,而不是
    窗口,因为它不是特定于浏览器的。谢谢,我还有一个后续问题…你选择3级深度定义有什么原因吗(即,
    global.MyApp.searchResult
    )而不是2(即,
    global.searchResult
    )?我想知道使用3级是否是一种最佳实践方法。@ayjay:所以我们只有一个全局:
    MyApp
    。我认为我在上面代码中对参数的命名非常混乱(我在中使用了
    global
    )“全局对象”包含全局变量),因此我将其更改为
    globals
    (因为“全局对象”包含全局变量)另外,我在设置全局变量的位前面添加了一个
    var MyApp=
    。MyApp
    这样我们就可以在iLife中使用
    MyApp
    。同时更新了pastie:我们在
    globals
    上放置的任何属性都会成为全局变量,所以我们希望将其保持在最小值(如果可能,为零,上面的一个)。我还有一个问题与您提供的答复有关(顺便说一句,我非常感谢所有的答复)。在处理文件之间的名称空间时,哪种方法更常用:或者?我了解这两种方法都有效,但我很好奇在现实世界中更遵循哪种约定。