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

时间:2014-06-20 23:06:23

标签: javascript closures iife

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

models.js

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

})();

controllers.js

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

现在我已经在它们上添加了闭包,我收到了一个错误searchResult在controllers.js中未定义 - 因为它无法看到它存在于models.js中。如何让它理解它存在于另一个文件中?

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

2 个答案:

答案 0 :(得分:3)

为了让他们互动,他们必须有一些共同的符号。你有几个选择:

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

  2. 使用某种类型的库(使用[理想]只需一个全局符号)

  3. 自己做一个不同的方式,根本不需要全局通用符号

  4. 自己动手

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

    这是有效的,因为在松散模式下,全局范围内的this是全局对象(浏览器上为window)。我们将其作为参数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);
    

    我们做同样的事情,除了controllers.js期待models.js已经运行。虽然我们仍然执行var MyApp = globals.MyApp = globals.MyApp || {};位,但如果new MyApp.searchResult尚未运行,models.js当然会失败。

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

    使用某种为您执行此操作的库

    您的另一个选择是使用像RequireJS这样的库(一个全局符号有require,它是一个函数)或任何其他asynchronous module definition库。

    以另一种方式自己动手

    另一个DIY选项完全摆脱全局 ,你甚至不需要一个全局。

    要做到这一点,你的个人文件没有IIFE(虽然他们可以使用那些他们不想与其他文件共享的东西):

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

    controllers.js:

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

    然后使用缩小器将脚本组合在一个大的IIFE中。您可能有pre.js

    (function() {
    

    post.js

    })();
    

    然后,缩放器通过组合app.js创建pre.js + models.js + controllers.js + post.js。最终结果(未缩小并在此处格式化以便于阅读)是:

    (function() {
        ;
        function searchResult (obj) {
          this.state = obj.State;
          /*Do more stuff */
        }
    
        ;
        function storeSearchResults(jsonObj) {
          var instance = new searchResult(jsonObj.data[i]);
          /* Do more */
        }
    })();
    

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

答案 1 :(得分:-2)

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

我不使用全局变量。

但是我不知道如何在原始javascript中使用事件或者是否可以完成数据传递。我使用jquery / node来传递数据并且工作得非常好。