命名空间的JavaScript库,作为可选

我即将开始build立一个有多个模块的JS库。 假设图书馆被称为图书馆,两个模块将被称为一个和两个。 我希望最终用户能够以两种不同的方式调用库:

Library.One.somefunction(params) 

要么

 somefunction(params) 

基本上,我想给最终用户select包含一个命名空间。 有没有一个好的方法来做到这一点? 另外,如果我还想提供图书馆的缩小版本,是否有这样做的好方法? 这个库是我可以在Node.js结束的东西; 现在我要自己去使用它,但是我想要这样devise,以便将来可以转向一个可共享的项目。

任何引用你可以指向我会很好,谢谢!

好吧,我不知道你的意思是什么“好方法”。
首先,命名空间的全部目的是收集相关的variables,而不是将它们散布在公共命名空间中。 就我个人而言,我不会使用这样的事情,但是你可以遍历你的命名空间的对象并将它们附加到窗口中:

 for(var i在命名空间中)
    如果(Namespace.hasOwnProperty(i))的
         window [i] = Namespace [i];

如果您使用Node.js ,则可以利用CommonJS模块系统。

math.js (你的图书馆)

 exports.add = function() { for (var i = arguments.length; i--;) { sum += arguments[i]; } return sum; }; 

program.js (使用它的人…)

 var MyMath = require('math'); console.log(MyMath.add(1, 2)); // 3 // ... in different ways var add = require('math').add; console.log(add(1, 2)); // 3 

使“命名空间”成为可选项的基本思想是将函数分配给作为window对象的全局作用域:

 window.somefunction = Library.One.somefunction; 

你可以编写一个类似于其他语言的include函数:

 var include = function (library, p) { if (!p) { for (var prop in library) { if (library.hasOwnProperty(prop)) { window[prop] = library[prop]; } } } else { window[p] = library[p]; } }; 

然后按要求做:

 include(Library.One); 

或仅使用特定function:

 include(Library.One, 'somefunction'); 

警告

  1. 不使用点符号( One.somefunction )执行函数将导致this关键字引用window而不是Library.One 。 如果你不使用this ,这不是一个问题。 如果你有数据要分配给函数之间,那么你可以使用闭包范围来代替this

     var Library = {}; (function () { // I'm a closure, I have local scope var sharedData = "I'm shared but private to this scope"; Library.One = {}; Library.One.funcOne = function () { alert(sharedData); }; Library.One.funcTwo = function () { sharedData += "!"; }; }) (); 
  2. 其他人则build议不要让你的方法成为全局的。 这是因为一旦它是全球性的,它是全球性的所有文件,因此可能与其他代码冲突。 你可以做的是修改上面的import函数来创build一个新对象,并在返回之前将所有对象分配给该对象。 然后,需要特定库的快捷方式的文件可以做到:

     (function () { var _ = include(Library.One); // This stays within this scope _.somefunction(); })(); 

你可以很容易地做到这一点,但你确定你想要使所有的方法全局属性?

你可以像这样实现它(非常简化):

 (function( window, undefined ) { // Your code setting up namespaces var Library = {One:{},Two:{}}; // function for adding library code to both namespaces. // Could be modified to accept an Array of functions/names function addToLibraryOne( id, fn ) { window[id] = Library.One[id] = fn; } // add a function addToLibraryOne( "somefunction", function( params ) { // function code }); window.Library = Library; })( window ); 

我想知道你是否真的想污染这样的全局命名空间。

至less,我会使global属性的选项,然后只有function添加这些,如果该选项被选中。

那么,第二个意味着你也希望你的模块中的函数和对象以及任何东西都在全局范围内。 当然,这是完全可能的,但最好的做法是有些可恶的。

对于第一部分,只需在全局声明库名称空间即可:

 var Library = {}; 

然后开始用你的模块填充它:

 Library.One = {}; Library.Two = {}; 

然后开始为这些模块添加function。

 (function($) { var $.froobString = function(s) { .... }; ...etc... })(Library.One); 

(在这里我已经做了一个自执行匿名函数,通过Library.One作为$

要将所有这些转换为全局variables,请执行如下的例程:

 var convertToGlobals = function(module) { for (name in module) { window[name] = module[name]; } }; convertToGlobals(Library.One) 

但是,我再次build议反对。

我可能是错的这个(所以这可能会被低估,但我希望这个评估),但我认为你正在build立一个矛盾的要求

1)我想使用命名空间
2)我想能够访问没有名称空间的名称空间function。

基本上2是“我不想命名空间”。

为了实现,你可以定义一些全局的函数路由到命名空间,但是为什么命名空间开始?