简体   繁体   English

我可以像这样模块化我的javascript代码吗?

[英]Can I modularize my javascript code like this?

I really don't like all of my javascript code ending up in just one file, I tried using libraries like require.js to help me modularize but they end up getting a little complex for me. 我真的不喜欢我的所有javascript代码只在一个文件中结束,我尝试使用像require.js这样的库来帮助我模块化但是它们最终让我变得有点复杂。 So I was wondering if I can do something like this. 所以我想知道我是否可以做这样的事情。

Context : Say I want a different module to take care of Random Number generation. 上下文:假设我想要一个不同的模块来处理随机数生成。 I create a new file (with a capital first letter my self made convention) 我创建了一个新文件(首字母是我自制的约会)

// File : RandomNumberGenerator.js

(function(){
    // export this to the outer world
    _randomGenerator = new RandomNumberGenerator();

    function RandomNumberGenerator() {
    }

    RandomNumberGenerator.prototype.getRandomNumber = function(rangeLower, rangeHigher) {
        if(rangeLower !== undefined && rangeHigher === undefined) { // user passed in just one parameter
            rangeHigher = rangeLower;
            rangeLower = 0;
        }else if (rangeLower === undefined && rangeHigher === undefined) {
            return (Math.random());
        }

        return (Math.floor((Math.random() * (rangeHigher - rangeLower)) + rangeLower));
    };
})();

Now _randomGenerator is visible to the global scope. 现在_randomGenerator对全局范围可见。 I added '_' as again a self made convention. 我添加'_'再次成为一个自制的约定。

Now I can use this in my main js file like 现在我可以在我的主要js文件中使用它

(function() {
    console.log(_randomGenerator.getRandomNumber(5));
})();

Can I do this? 我可以这样做吗? Is there something I am overlooking that can cause problems in the long run? 从长远来看,我有什么东西可以解决问题吗? Is there a possibility of polluting the global scope by doing something like this ? 通过做这样的事情是否有可能污染全球范围?

What you've described is the Immediately invoked function expression module pattern. 您所描述的是立即调用的函数表达式模块模式。

To export functions and objects you need to attach them to the global window object, usually it's recommended you place them under a namespace to avoid collisions with other code: 要导出需要将它们附加到全局window对象的函数和对象,通常建议您将它们放在命名空间下以避免与其他代码冲突:

(function() {

    function RandomNumberGenerator() {
    }

    RandomNumberGenerator.prototype.getRandomNumber = function(rangeLower, rangeHigher) {
        ...
    };

    // Create new namespace
    window.MyModule = {};

    // Export the RandomNumberGenerator
    window.MyModule.RandomNumberGenerator = RandomNumberGenerator;

    // Export a single instance
    window.MyModule.defaultRandomNumberGenerator = new RandomNumberGenerator();
})();

You can also import values into an IIFE, which allows you to create aliases: 您还可以将值导入IIFE,从而可以创建别名:

(function(rng, max) {

    console.log(rng.getRandomNumber(max));

})(MyModule.defaultRandomNumberGenerator, 5);

Can I do this? 我可以这样做吗?

Yes

Is there something I am overlooking that can cause problems in the long run? 从长远来看,我有什么东西可以解决问题吗?

Don't let your IIFE's get too big, or you'll lose the benefit. 不要让你的IIFE变得太大,否则你将失去利益。 Small well-defined modules are easier to maintain. 小型明确定义的模块更易于维护。

Also if you want two modules to share the same namespace you'll need to do something more elaborate than my example above otherwise one module will overwrite the other. 此外,如果你想要两个模块共享相同的命名空间,你需要做一些比我上面的例子更精细的事情,否则一个模块将覆盖另一个模块。

IIFE's can hold state but they are effectively singletons, try to ensure you create objects and put any state in those to avoid global state . IIFE可以保持状态,但它们实际上是单身,试图确保你创建对象并将任何状态置于那些状态以避免全局状态

Is there a possibility of polluting the global scope by doing something like this? 通过做这样的事情是否有可能污染全球范围?

Yes it is possible; 对的,这是可能的; you should still name your namespace carefully - don't use window.jQuery for example! 你仍然应该仔细命名你的命名空间 - 例如,不要使用window.jQuery

Yes, you can do that. 是的,你可以这么做。 In fact, it's a very frequent pattern. 事实上,这是一种非常频繁的模式。 It's commonly combined with automatic concatenation of the JS files, keeping the distinction between the source files (unconcatenated) and the production file (concatenated, and also often minified). 它通常与JS文件的自动连接相结合,保持源文件 (非复杂的)和生产文件 (连接,也经常缩小)之间的区别。

Just be explicit that you're creating a property of the window object. 只是明确表示您正在创建窗口对象的属性。 Change 更改

_randomGenerator = new RandomNumberGenerator();

to

window._randomGenerator = new RandomNumberGenerator();

This explicit declaration is mandatory in strict mode . 严格模式下,此显式声明是必需的。

Whilst you can modularize your code like that, you are still potentially introducing a large number of global variables. 虽然您可以像这样模块化代码,但您仍然可能会引入大量全局变量。 You are using a defensive strategy, by adding the _ prefix, but it's still safer not to have them there at all. 你正在使用一种防御策略,通过添加_前缀,但是根本不让它们在那里更安全。

You only actually need one for a module pattern. 实际上,您只需要一个模块模式。 So long as your first file has something like this: 只要你的第一个文件有这样的东西:

window.module = {};

Then the rest of your modules, can just register themselves as properties on the module object, without having to contort their names. 然后,其余模块可以将自己注册为模块对象的属性,而不必扭曲它们的名称。

module.randomNumberGenerator = new RandomNumberGenerator();

function RandomNumberGenerator() {
  ...
}    

Then in any another file you can use that instance. 然后在任何其他文件中,您可以使用该实例。

var rng = module.randomNumberGenerator;
// ...
var number = rng.getRandomNumber();

That works, but it's overly complicated unless you have some data declared that you need to put in the scope to keep it isolated. 这是有效的,但它过于复杂,除非你声明一些数据需要放入范围以保持隔离。

For your example, you can just create the object directly, instead of having a constructor to create just a single instance: 对于您的示例,您可以直接创建对象,而不是只使用构造函数来创建单个实例:

// File : RandomNumberGenerator.js

_randomGenerator = {

    getRandomNumber: function(rangeLower, rangeHigher) {
        if(rangeLower !== undefined && rangeHigher === undefined) { // user passed in just one parameter
            rangeHigher = rangeLower;
            rangeLower = 0;
        }else if (rangeLower === undefined && rangeHigher === undefined) {
            return (Math.random());
        }

        return (Math.floor((Math.random() * (rangeHigher - rangeLower)) + rangeLower));
    }

}

If you have a class, you still don't need to wrap it in a scope if you don't have any static data for it: 如果你有一个类,如果你没有任何静态数据,你仍然不需要将它包装在一个范围内:

function SomeClass() {
  // ...
}

SomeClass.prototype.someMethod = function(){
  // ...
}

You would use a scope if you have some static data for classes, for example to keep track of all instances: 如果您有类的静态数据,则可以使用范围,例如跟踪所有实例:

var SomeClass = (function(){

  var instances = [];

  function SomeClass() {
    instances.push(this);
  }

  SomeClass.prototype.getAllInstances = function(){
    return instances;
  }

  // expose the constructor
  return SomeClass;

})();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在JavaScript中模块化我的代码? - How do I modularize my code in JavaScript? 我想模块化Backbone.js视图,以便Javascript和模板位于同一个文件中 - I would like to modularize Backbone.js views so that Javascript and Templates are located in the same file 我可以仅使用Javascript代码拖动DOM元素吗? (例如,如果我用鼠标拖动它) - Can I drag a DOM element with Javascript code only? (like If I dragged it with my mouse) 我如何模块化静态HTML文件? - How I can modularize static HTML file? 如何轻松地将 Javascript 模块化,如 C/C++ - How to easily modularize Javascript like C/C++ 在 JavaScript 中创建 HTML 元素时如何模块化代码? - How to modularize code while creating HTML elements in JavaScript? 如何压缩代码中的Javascript? - How can I compress the Javascript in my code? 如何使用JavaScript在我的视图中重复C#代码的特定块,甚至应该那样做? - How can I repeat specific block of C# code in my View using javascript and should that even be done like that or? “如何用Javascript编写二维数组输入,使其看起来像这样?” - “How can I code a 2 dimension array input in Javascript such that it looks like this?” 我如何在网站中像字符串一样显示html代码和javascript - How can i show html code and javascript like a string in website
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM