【问题标题】:How can I split a javascript application into multiple files?如何将 javascript 应用程序拆分为多个文件?
【发布时间】:2012-02-03 21:00:06
【问题描述】:

我创建了一个 javascript 应用程序,其中所有代码都在一个文件中。该应用程序已经增长了很多,我认为是时候将其拆分为多个文件了,但我很难弄清楚如何做到这一点。我认为问题在于我决定如何构建应用程序,它使用以下模板:

var myApp = function(){

    //there are several global variables that all of the modules use;
    var global1, global2, module1, module2;

    global1 = {
        prop1:1
    };

    //There are also several functions that are shared between modules
    function globalFunction(){

    }

    var ModuleOne = function(){

        function doSomething(){
            //using the global function
            globalFunction();
        }

        return{
            doSomething:doSomething
        }
    };

    var ModuleTwo = function(){

        function doSomething(){
            //module 2 also needs the global function
            globalFunction();

            //Use the functionality in module 1
            //I can refactor this part to be loosely coupled/event driven
            module1.doSomething();
        }
    };

    module1 = new ModuleOne();
    module2 = new ModuleTwo();
};

即使所有模块都是松散耦合和事件驱动的,我仍然不知道如何将其拆分为多个文件,因为每个模块都依赖于共享函数/变量。有人有建议吗?

【问题讨论】:

  • 说真的,像module8 这样的工具可以解决您的问题
  • 看看这篇文章中的设计模式:adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth - 您可以将模块定义拆分到多个文件中,这样可以共享通用属性,也可以创建变量或方法仅对特定文件是私有的。
  • @nnnnnn 谢谢。我现在去看看。
  • @nnnnnn 感谢那篇文章。这是完美的。您应该提交带有链接的答案,以便我接受...
  • 如果模块使用共享函数/变量,那么它们就不是松散耦合的。

标签: javascript oop


【解决方案1】:

试一试 require.js。 http://requirejs.org/

例子:

require(["dir/file"], function() {
    // Called when file.js loads
});

【讨论】:

  • 是的,我研究过了,但我仍然不知道如何解决共享函数的问题...
  • 但这如何帮助拆分当前相互依赖的大型代码文件?
  • 您为每个类创建一个文件(因此是 OOP 标记),运行的脚本只需拉取这些类以供使用。如果您向我展示代码,我可以帮助您将其分发到文件中。
  • @fabianhjr 代码的结构与问题中包含的示例完全相同。您将如何拆分该样本?谢谢。
  • @fabianhjr 无需猜测。结构存在问题,我在该结构中遇到的具体问题也是如此。我的问题是寻求有关如何解决这些问题的建议。如果除了将其称为“设计问题”之外没有其他建议,为什么还要回复?
【解决方案2】:

您可以将共享函数和共享模块放在 myApp 对象上,这样它们就不会污染全局命名空间,而是可以在任何地方访问,而无需在同一个闭包内。

myApp.moduleOne = function() {...}
myApp.moduleTwo = function() {...}
myApp.globalFunction = function() {...}

然后,您可以在任何文件中定义它们并在任何文件中使用它们。

您也可以将文件分成多个文件,但要求它们以特定顺序包含,以保留您的关闭。如果您出于实际编辑原因拆分文件,但为了实际部署而重新组合和最小化它们,那么这不会在您如何编写代码或如何部署方面花费您任何费用,但会给您提供许多较小的文件为了编辑方便。

【讨论】:

  • myApp 不是真名,我只是用它来举例。鉴于您的建议,我需要将对 globalFunction 的每次调用更改为 myApp.globalFunction() 正确吗?
  • @MarkBrown - 正确。在编写代码时它不太理想,但可以让您更灵活地将代码分割成完全独立的文件,这些文件可以更加独立。我也为我的答案添加了另一个选项。
【解决方案3】:

我最喜欢的解决方案是使用服务器端脚本将其他文件包含在我的“主”文件中。例如,使用 Perl 的模板工具包:

var myApp = function(){
    [% INCLUDE lib/module1.js %]
    [% INCLUDE lib/module2.js %]
    [% INCLUDE lib/module3.js %]
}

或 PHP:

var myApp = function(){
  <?php
    include 'lib/module1.js';
    include 'lib/module2.js';
  ?>
}

【讨论】:

  • 这是动态构建的javascript。应该避免这种情况,以支持静态编译而不是动态包含。
  • TT 和 PHP 都可以从控制台运行,因此如果您需要静态编译,您可以轻松编写构建脚本。哦,加上TT可以配置缓存文件,所以编译只需要发生一次。
【解决方案4】:

看看这篇文章中的设计模式:http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth - 您可以将模块定义拆分到多个文件中,这样既可以共享公共属性,又可以创建仅对特定文件。

基本思想是单个 JS 文件添加到同一个模块,代码如下:

var MODULE = (function (my) {
     var privateToThisFile = "something";

    // add capabilities...

     my.publicProperty = "something";

    return my;
}(MODULE || {}));

如果 MODULE 已经定义(来自另一个 JS 文件),则在每个 JS 文件的哪个位置添加,否则创建它。您可以对其进行设置,以便(大多数情况下)不管各种文件包含在什么顺序中。

文章详细介绍了几种变化,当然您可能会想出自己的调整...

【讨论】:

  • 经过一整天的思考后,我很高兴找到了这个答案。
【解决方案5】:

不是为了增加混乱,而是来自 C++ 背景,我试图以下面描述的方式构造类似于 c++ 命名空间的东西。它有效,但我想知道这是否是 OP 可接受的模式?

-------------------------------- 文件 main.js:---------- ------

var namespacename = function(){}

namespacename.mainvalue = 5;

namespacename.maintest = function() {
    var cm = new namespacename.game();
    cm.callme();
}

--------------------------------文件 game.js:---------- ------

namespacename.gamevalue = 15;

namespacename.game = function(){
    this.callme = function(){
        console.log( "callme" );
    }
}

namespacename.gametest = function() {
    console.log( "gametest:gamevalue:" + this.gamevalue );
    console.log( "gametest:mainvalue:" + this.mainvalue );
}

--------------------------------文件 index.html:---------- ----

<html>
    <head>
        <title>testbed</title>
    </head>

    <body onload="init();">
    </body>

    <script type="text/javascript" src="main.js"></script>
    <script type="text/javascript" src="game.js"></script>

    <script type="text/javascript">

        init = function() 
        {
            namespacename.maintest();
            namespacename.gametest();

            console.log( "html main:" + namespacename.mainvalue );
            console.log( "html game:" + namespacename.gamevalue );
        }

   </script>
</html>

【讨论】:

  • 为什么将 namespacename 声明为一个永远不会被调用的空函数?您可以使用 var namespacename = {} 将其声明为空对象,其余代码无需更改。
  • 如果你来自 C++,你必须知道你会以几十个,有时是成百上千个文件结束。您不想从服务器请求那么多 js 脚本。相反,最好将所有文件打包在 1 个脚本中(例如使用 webpack)
猜你喜欢
  • 2015-07-24
  • 2021-12-06
  • 1970-01-01
  • 1970-01-01
  • 2015-01-13
  • 1970-01-01
  • 2012-03-13
  • 1970-01-01
  • 2021-04-19
相关资源
最近更新 更多