【问题标题】:How can I seperate objects that is under same closure into different files如何将同一闭包下的对象分隔到不同的文件中
【发布时间】:2010-08-12 07:34:04
【问题描述】:

我的客户有以下结构;

var myObject = (function(){
    var mainObjectList = [];
    var globalObject = {
            init:function(mainObjectId){
                var logger = {};
                var utilityObject1 = {};
                var utilityObject2 = {};
                var mainObject = {};
                mainObjectList.push(mainObject);
            },//init
            someOtherMethods:function(){}
        };//globalObject
    return globalObject;
})();

我可以和我的客户说 myObject.init(5); 并创建一个新结构。 我的问题是我在 init 函数闭包中有很多实用程序对象(logger、utilityObject1、utilityObject2 ..)。我的总文件超过了 1000 行,所以我想将所有实用程序对象分成不同的文件,以获得更好的项目。例如,我可以将 logger、utilityObject1、utilityObject2 分离到他们自己的文件中。问题是由于对象已关闭,因此我不能仅将它们添加到单独文件中的主对象中。所以我想到了下面的注入方法。

//start of file1
var myObject = (function(){
    var mainObjectList = [];
    var globalObject = {
            init:function(mainObjectId){
                var logger;
                var utilityObject1 = {};
                var utilityObject2 = {};
                var mainObject = {};
                mainObjectList.push(mainObject);
            },//init
            someOtherMethods:function(){},
            injectLogger:function(creator){
                this.logger = creator();
            }
        };//globalObject
    return globalObject;
})();
//start of file2
myObject.injectLogger(function(){return {};});

这样我就可以分离我的文件进行开发。但在生产中,我可以将文件连接成一个文件。但是我对这个设计有一些问题。我刚刚在 myObject 中添加了一个可访问的 injectLogger 函数。我的记录器现在不能在关闭中使用其他局部变量(我现在必须将它们传递给创建者对象)。我的问题是有没有其他方法可以将这种代码分成文件。 (可能是外部实用程序。)

【问题讨论】:

    标签: javascript closures


    【解决方案1】:

    我喜欢用google的闭包编译器http://code.google.com/closure/compiler/

    如果你不想使用类似的东西,你可以尝试这样的事情:(确保你首先加载 globalObject.js 来定义变量)。

    //globalObject.js
    var globalObject = function() {
    
    }
    
    //init.js
    globalObject.prototype.init = function() {
        this.utilityFunction();
        //do something with utilityObject1
        this.utilityFunction(this.utilityObject1);
    }
    
    //utilityFunction.js
    globalObject.prototype.utilityFunction= function() {}
    
    //utilityObject1.js
    globalObject.prototype.utilityObject1 = {};
    
    //main.js
    var myObject = new globalObject();
    myObject.init();
    

    然后您可以通过执行以下操作来覆盖该函数:

    //main.js
    var myObject = new globalObject();
    myObject.utilityFunction = function() {
        //new function
    }
    myObject.init(); // This will then use the new utilityFunction method you just set.
    

    【讨论】:

      【解决方案2】:

      据我了解,您希望拥有一些所有模块都关闭的词法变量,但您希望将各个模块的代码保存在不同的文件中。

      实现这种精确行为的一种方法是通过将模块定义连接在一起来创建单个 Javascript 文件:

      Header.js-部分

      var myObject = (function(){
          var mainObjectList = [];
          var globalObject = {
                  init:function(mainObjectId){
      

      Logger.js:

      function Logger() { this.enabled = true; }
      Logger.prototype.log = function() {
        if (window.console && window.console.log) {
           return window.console.log.apply(window.console.log, arguments]);
        }
      }
      

      根据需要添加其他模块文件。它们可以引用词法变量。

      Footer.js-部分

          }// end init
      }; // end globalObject
      return globalObject;
      

      })();

      最后,您需要一个脚本,将所有这些文件连接到一个 js 文件中。没有其他方法可以在纯 Javascript 中获得真正的词法变量访问。

      更好的选择

      也就是说,这种技术很容易混淆,我不推荐它。闭包通常用于关闭局部变量,而不是程序范围的变量。如果您使用 1000 行前声明的词法变量,您将花费一些时间来跟踪在运行程序时声明所有变量的位置。相反,您可能应该在globalObject 中包含私有的“全局”数据。例如,将mainObjectList 存储在globalObject.mainObjectList 中并在模块文件中引用它。

      我推荐一种类似于 nemophrost 描述的解决方案。每个文件本身都应该是有效的 javascript。

      【讨论】:

        【解决方案3】:

        您可以使用命令行 PHP 作为预处理器来组合您的文件。例如,main.js.php 可能如下所示:

        (function() {
            <?php require('foo.js.php');?>
        })();
        

        然后在您想要生成可用于缩小和部署的输出文件时运行命令php main.js.php &gt; combined.js

        这样做的好处是您可以将main.js.php 加载到服务器上以测试新版本的代码而无需重新编译。您可以在main.js.php 的开头放一行,让 PHP 发送正确的 MIME 类型:

        <?php header('Content-type: text/javascript');?>
        

        【讨论】:

          【解决方案4】:

          我处理这个问题的方式是检查全局对象是否存在,如果不存在则创建它。这样顺序就不重要了。

          // file 1
          var Global_Obj = Global_Obj || {};  // creates empty global object
          Global_Obj.An_Obj = { /* stuff */ };
          
          // file 2
          var Global_Obj = Global_Obj || {}; // uses created global object
          Global_Obj.Another_Obj = { /* stuff */ };
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-09-09
            • 2019-09-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-06-29
            相关资源
            最近更新 更多