命名 javascript 库(可选)

发布于 2024-10-13 09:17:25 字数 382 浏览 4 评论 0原文

我即将开始构建一个包含多个模块的 JS 库。假设该库名为“Library”,两个模块名为“一”和“二”。我希望最终用户能够以两种不同的方式调用该库:

Library.One.somefunction(params)

或者

somefunction(params)

基本上,我想为最终用户提供包含或不包含命名空间的选项。有没有好的方法可以做到这一点?另外,如果我还想提供该库的缩小版本,有没有好的方法可以做到这一点?这个库是我最终可以在 Node.js 中使用的东西;现在,我要自己使用它,但我想以这样的方式设计它,以便将来转变成可共享的项目并不太难。

如果您能指出我的任何参考文献那就太好了,谢谢!

I'm about to start building a JS library that will have multiple modules. Let's suppose the library is called Library, and two modules will be called One and Two. I'd like for end users to be able to call the library in two different ways:

Library.One.somefunction(params)

or

somefunction(params)

Basically, I want to give the end users the option of including a namespace or not. Is there a good way to do this? Also, is there a good way to do this if I also want to provide a minified version of the library? This library is something that I could end up in Node.js; for now, I'm going to use it myself, but I want to design it in such a way that it's not too hard to turn in to a sharable project in the future.

Any references you can point me to would be great, thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

吖咩 2024-10-20 09:17:25

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

ma​​th.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

If you're using Node.js you could leverage the CommonJS module system.

math.js (your library)

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

program.js (someone using it...)

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
北笙凉宸 2024-10-20 09:17:25

使“命名空间”可选的基本思想是将函数分配给全局范围,即 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);

或仅使用特定函数:

include(Library.One, 'somefunction');

警告

  1. 执行不带点符号的函数(One.somefunction)将导致this 关键字引用 window 而不是 Library.One。如果您根本不使用 this,这不是问题。如果您有数据要在函数之间共享,那么您可以使用闭包作用域而不是 this 来实现:

    var 库 = {};
    
    (功能 () {
        // 我是一个闭包,我有本地范围
        var sharedData = "我是共享的,但在此范围内是私有的";
    
        库.One = {};
    
        Library.One.funcOne = function () {
            警报(共享数据);
        };
    
        Library.One.funcTwo = 函数 () {
            共享数据+=“!”;
        };
    
    }) ();
    
  2. 其他人建议不要使您的方法成为全局的。这是因为一旦它是全局的,它对于所有文件都是全局的,因此可能与其他代码发生冲突。您可以做的是修改上面的 import 函数来创建一个新对象,并在返回该对象之前将所有内容分配给该对象。然后需要特定库快捷方式的文件可以执行以下操作:

    <前><代码>(函数(){
    var _ = include(Library.One); // 这保持在这个范围内
    _.somefunction();
    })();

The basic idea behind making a "namespace" optional is to assign the functions to the global scope, which is the window object:

window.somefunction = Library.One.somefunction;

You can write an include function that works similar to other languages:

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];
    }
};

Then just do, as required:

include(Library.One);

Or use particular functions only:

include(Library.One, 'somefunction');

Warnings:

  1. Executing the functions without the dot notation (One.somefunction) will cause the this keyword to refer to window rather than Library.One. This isn't a problem if you don't use this at all. If you have data to share to between functions then you can do so using closure scope instead of 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. Others have well-advised not to make your methods global. This is because once it is global, it is global for all files, and therefore likely to conflict with other code. What you can do is modify the import function above to create a new object, and assign everything to that object before returning it. Then files that need shortcuts to particular libraries can do:

    (function () {
        var _ = include(Library.One); // This stays within this scope
        _.somefunction();
    })();
    
天煞孤星 2024-10-20 09:17:25

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

for(var i in Namespace)
    if(Namespace.hasOwnProperty(i))
        window[i] = Namespace[i];

well, i don't know what you mean by "good way".
First of all, the whole purpose of a namespace is to collect variables that are related and not scatter them all around your public namespace.
Personally I wouldn't use such a thing, but you could loop through your namespace's objects and attach them to the window :

for(var i in Namespace)
    if(Namespace.hasOwnProperty(i))
        window[i] = Namespace[i];
绮烟 2024-10-20 09:17:25

您可以很容易地做到这一点,但是您确定要使所有方法都成为全局属性吗?

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

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

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

至少,我会将 global 属性设置为一个选项,然后只有在选择该选项时才让函数添加这些属性。

You could do this pretty easily, but are you certain you want to make all the methods global properties?

You could implement it like this (very simplified):

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

I'd wonder if you really want to pollute the global namespace like this.

At the very least, I'd make the global properties an option, then only have the function add those if that option is selected.

爱的十字路口 2024-10-20 09:17:25

好吧,第二个意味着您还希望模块中的函数和对象以及任何内容都位于全局范围内。当然完全有可能,但是违背最佳实践,有点令人厌恶。

对于第一部分,只需全局声明您的库命名空间:

var Library = {};

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

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

然后开始向这些模块添加功能。

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

(这里我将其作为一个自动执行的匿名函数来完成,该函数将 Library.One 作为 $ 传入。)

要将所有这些转换为全局变量,请使用如下例程:

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

但我还是建议不要这么做。

Well, the second one means that you also want the functions and object and whatever in your modules to be in the global scope. Entirely possible of course, but so against best practices as to be somewhat abhorrent.

For the first part, just declare your Library namespace globally:

var Library = {};

and then start populating it with your modules:

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

and then start adding the functionality to those modules.

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

(Here I've done it as a self-executing anonymous function that passes in Library.One as $.)

To convert all that to globals, have a routine like this:

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

But then again I'd advise against it.

不知在何时 2024-10-20 09:17:25

我对此可能是错的(所以这可能会被否决,但我希望对其进行评估),但我认为您正在与要求相矛盾

1)我想使用命名空间
2)我希望能够在没有命名空间的情况下访问命名空间功能。

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

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

I might be wrong about this (so this might get downvoted, but I want this evaluated), but I think you are setting up a contradiction with the requirements

1) I want to use namespaces
2) I want to be able to access namespace functionality without the namespace.

basically 2 is "I dont want namespaces".

For implementation, you could just define a bunch of functions globally that route into the namespace, but then why have the namespace to begin with?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文