使用名称空间和子名称空间创建JavaScript文件的更好方法

使用名称空间和子名称空间创建JavaScript文件的更好方法,javascript,Javascript,我在寻找最好的解决方案——在任意数量的JavaScript文件中使用名称空间和子名称空间的最佳解决方案。我读了很多关于StackOverflow的文章和答案,我的选择是 但我有一个问题,即如何避免仅使用子名称空间定义向每个文件添加名称空间定义: // How to avoid namespace definition var appModule = (function(ns) { return ns; }(appModule || {})); // I want to have only

我在寻找最好的解决方案——在任意数量的JavaScript文件中使用名称空间和子名称空间的最佳解决方案。我读了很多关于StackOverflow的文章和答案,我的选择是

但我有一个问题,即如何避免仅使用子名称空间定义向每个文件添加名称空间定义:

// How to avoid namespace definition
var appModule = (function(ns) {
  return ns;
}(appModule || {}));

// I want to have only this
appModule.sub2 = (function (ns) {
  ns.publicFunction5 = function() {
    console.log('publicFunction5 from sub2AppModule.js');
  };

  return ns;
}(appModule.sub2 || {})); 
纯JavaScript中,在多个文件中使用名称空间和子名称空间可能是更好的方法

我举了一个完整的例子来更好地理解我的情况

index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Test namespace and sub-namespace in multiple files</title>
    <!-- order is intentional to check any order attaching files -->
    <script src="sub2AppModule.js"></script>
    <script src="sub1AppModule2.js"></script>
    <script src="sub1AppModule.js"></script>
    <script src="appModule2.js"></script>
    <script src="appModule.js"></script>
    <script>
      function testNamespace() {
        console.log(appModule.publicVariable1);
        appModule.publicFunction1();
        appModule.publicFunction2();
        appModule.sub1.publicFunction3();
        appModule.sub1.publicFunction4();
        appModule.sub2.publicFunction5();
      }
    </script>
  </head>

  <body>
    <h1>Test namespace</h1>
    <button onclick="testNamespace()">Run test</button>
  </body>

</html>
appModule2.js

var appModule = (function(ns) {
  var privateVariable1 = 'privateVariable1';

  function privateFunction1() {
    console.log('privateFunction1 from appModule.js');
  }

  ns.publicVariable1 = 'publicVariable1 from appModule.js'; 

  ns.publicFunction1 = function() {
    console.log('publicFunction1 from appModule.js');
    console.log('publicFunction1 display  ' + privateVariable1);
    console.log('publicFunction1 call ' + privateFunction1());
    // Call function from nested namespace
    appModule.sub2.publicFunction5();
  };

  return ns;
}(appModule || {}));
var appModule = (function(ns) {
  ns.publicFunction2 = function() {
    console.log('publicFunction2 from appModule2.js');
  };

  return ns;
}(appModule || {}));
var appModule = (function(ns) {
  return ns;
}(appModule || {}));

appModule.sub1 = (function(ns) {
  ns.publicFunction3 = function() {
    console.log('publicFunction3 from sub1AppModule.js');
    // Call function from parent namespace
    appModule.publicFunction2();
  };

  return ns;
}(appModule.sub1 || {}));
var appModule = (function(ns) {
  return ns;
}(appModule || {}));

appModule.sub1 = (function (ns) {
  ns.publicFunction4 = function() {
    console.log('publicFunction4 from sub1AppModule2.js');
  };

    return ns;
}(appModule.sub1 || {}));
var appModule = (function(ns) {
  return ns;
}(appModule || {}));

appModule.sub2 = (function (ns) {
  ns.publicFunction5 = function() {
    console.log('publicFunction5 from sub2AppModule.js');
  };

    return ns;
}(appModule.sub2 || {}));
sub1AppModule.js

var appModule = (function(ns) {
  var privateVariable1 = 'privateVariable1';

  function privateFunction1() {
    console.log('privateFunction1 from appModule.js');
  }

  ns.publicVariable1 = 'publicVariable1 from appModule.js'; 

  ns.publicFunction1 = function() {
    console.log('publicFunction1 from appModule.js');
    console.log('publicFunction1 display  ' + privateVariable1);
    console.log('publicFunction1 call ' + privateFunction1());
    // Call function from nested namespace
    appModule.sub2.publicFunction5();
  };

  return ns;
}(appModule || {}));
var appModule = (function(ns) {
  ns.publicFunction2 = function() {
    console.log('publicFunction2 from appModule2.js');
  };

  return ns;
}(appModule || {}));
var appModule = (function(ns) {
  return ns;
}(appModule || {}));

appModule.sub1 = (function(ns) {
  ns.publicFunction3 = function() {
    console.log('publicFunction3 from sub1AppModule.js');
    // Call function from parent namespace
    appModule.publicFunction2();
  };

  return ns;
}(appModule.sub1 || {}));
var appModule = (function(ns) {
  return ns;
}(appModule || {}));

appModule.sub1 = (function (ns) {
  ns.publicFunction4 = function() {
    console.log('publicFunction4 from sub1AppModule2.js');
  };

    return ns;
}(appModule.sub1 || {}));
var appModule = (function(ns) {
  return ns;
}(appModule || {}));

appModule.sub2 = (function (ns) {
  ns.publicFunction5 = function() {
    console.log('publicFunction5 from sub2AppModule.js');
  };

    return ns;
}(appModule.sub2 || {}));
sub1AppModule2.js

var appModule = (function(ns) {
  var privateVariable1 = 'privateVariable1';

  function privateFunction1() {
    console.log('privateFunction1 from appModule.js');
  }

  ns.publicVariable1 = 'publicVariable1 from appModule.js'; 

  ns.publicFunction1 = function() {
    console.log('publicFunction1 from appModule.js');
    console.log('publicFunction1 display  ' + privateVariable1);
    console.log('publicFunction1 call ' + privateFunction1());
    // Call function from nested namespace
    appModule.sub2.publicFunction5();
  };

  return ns;
}(appModule || {}));
var appModule = (function(ns) {
  ns.publicFunction2 = function() {
    console.log('publicFunction2 from appModule2.js');
  };

  return ns;
}(appModule || {}));
var appModule = (function(ns) {
  return ns;
}(appModule || {}));

appModule.sub1 = (function(ns) {
  ns.publicFunction3 = function() {
    console.log('publicFunction3 from sub1AppModule.js');
    // Call function from parent namespace
    appModule.publicFunction2();
  };

  return ns;
}(appModule.sub1 || {}));
var appModule = (function(ns) {
  return ns;
}(appModule || {}));

appModule.sub1 = (function (ns) {
  ns.publicFunction4 = function() {
    console.log('publicFunction4 from sub1AppModule2.js');
  };

    return ns;
}(appModule.sub1 || {}));
var appModule = (function(ns) {
  return ns;
}(appModule || {}));

appModule.sub2 = (function (ns) {
  ns.publicFunction5 = function() {
    console.log('publicFunction5 from sub2AppModule.js');
  };

    return ns;
}(appModule.sub2 || {}));
sub2AppModule.js

var appModule = (function(ns) {
  var privateVariable1 = 'privateVariable1';

  function privateFunction1() {
    console.log('privateFunction1 from appModule.js');
  }

  ns.publicVariable1 = 'publicVariable1 from appModule.js'; 

  ns.publicFunction1 = function() {
    console.log('publicFunction1 from appModule.js');
    console.log('publicFunction1 display  ' + privateVariable1);
    console.log('publicFunction1 call ' + privateFunction1());
    // Call function from nested namespace
    appModule.sub2.publicFunction5();
  };

  return ns;
}(appModule || {}));
var appModule = (function(ns) {
  ns.publicFunction2 = function() {
    console.log('publicFunction2 from appModule2.js');
  };

  return ns;
}(appModule || {}));
var appModule = (function(ns) {
  return ns;
}(appModule || {}));

appModule.sub1 = (function(ns) {
  ns.publicFunction3 = function() {
    console.log('publicFunction3 from sub1AppModule.js');
    // Call function from parent namespace
    appModule.publicFunction2();
  };

  return ns;
}(appModule.sub1 || {}));
var appModule = (function(ns) {
  return ns;
}(appModule || {}));

appModule.sub1 = (function (ns) {
  ns.publicFunction4 = function() {
    console.log('publicFunction4 from sub1AppModule2.js');
  };

    return ns;
}(appModule.sub1 || {}));
var appModule = (function(ns) {
  return ns;
}(appModule || {}));

appModule.sub2 = (function (ns) {
  ns.publicFunction5 = function() {
    console.log('publicFunction5 from sub2AppModule.js');
  };

    return ns;
}(appModule.sub2 || {}));

为什么你只是为了好玩而让生活变得更艰难?。。。在没有代码组织结构(如闭包、匿名和自执行函数)的语言中,名称空间是必须的,但您正在使用Javascript编程,您已经拥有了所有这些。实际上,Javascript中几乎不需要名称空间,也绝对不需要子名称空间,所以为什么要浪费时间、精力和CPU周期来实现一个没有真正好处的范例呢?。。。为什么不开发一个函数来按正确的顺序加载代码并解决问题呢?它并没有那么简单。我有很多应用程序使用一个通用工具JavaScript代码(我们的和extern—大量JavaScript文件)。在这些应用程序中,应用程序文件中变量和函数的名称与公共文件中变量和函数的名称存在冲突。因此,我必须给出一些技巧来解决这些应用程序中的冲突。我确实理解您的问题,但是我无法找到导致额外复杂性的有效原因。您没有动态加载文件,因此所有文件都将在testNameSpace执行之前加载,并且由于这一事实,将sub1绑定到appModule是一个选项,但不是必需的需求,因此您可以使用:appModuleSub1将其保持一个级别的深度。从我的角度来看,除非你已经有了动态加载文件的计划,否则我认为没有理由免费让你的生活复杂化。因为你是从HTML代码加载文件的,所以我看不到appModule.sub1和appModuleSub1在功能上有什么区别,所以如果我是你,我会让我的生活更简单。我从来没有说过模块模式是错误的答案,你的方法是正确的,但是看看你的代码,我认为不需要第二级的复杂性,但是如果你觉得你确实需要,避免在子模块内创建父名称空间的唯一方法是确保所有文件都以正确的顺序加载和执行,否则您将无法以安全的方式将其删除。您必须了解,代码的存在是为了防止在加载模块之前加载子模块,因此,您可以进行优化,但您无法避免该步骤,除非您可以绝对肯定在模块之前不会加载或执行任何子模块。