我可以模块化我的javascript代码像这样
Can I modularize my javascript code like this?
我真的不喜欢我所有的javascript代码结束在一个文件中,我尝试使用像require.js这样的库来帮助我模块化,但它们最终对我来说有点复杂。所以我想知道我是否可以做这样的事情。
背景:假设我想要一个不同的模块来处理随机数的生成。我创建了一个新文件(首字母大写是我自己做的惯例)
// 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));
};
})();
现在_randomGenerator
对全局作用域是可见的。我又加上了一个"_",这是我自己的习惯。
现在我可以在我的主js文件中使用它,如
(function() {
console.log(_randomGenerator.getRandomNumber(5));
})();
我可以这样做吗?有没有什么我忽略了的东西,从长远来看可能会导致问题?这样做有可能污染全局范围吗?
您所描述的是立即调用的函数表达式模块模式。
要导出函数和对象,您需要将它们附加到全局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();
})();
您还可以将值导入到IIFE中,它允许您创建别名:
(function(rng, max) {
console.log(rng.getRandomNumber(max));
})(MyModule.defaultRandomNumberGenerator, 5);
我可以这样做吗?
是的
是否有一些我忽略了,可能导致长期问题?
不要让你的生活太大,否则你会失去好处。定义良好的小模块更容易维护。
如果你想让两个模块共享相同的命名空间,你需要做一些比我上面的例子更复杂的事情,否则一个模块会覆盖另一个。
IIFE可以保存状态,但它们是有效的单例,尽量确保创建对象并将任何状态放入其中以避免全局状态。
这样做是否有可能污染全局作用域?
是的这是可能的;你仍然应该小心命名你的命名空间——比如不要使用window.jQuery
!
可以。事实上,这是一种非常常见的模式。它通常与JS文件的自动连接相结合,保持源文件(未连接)和生产文件(连接,也经常缩小)之间的区别。
要明确你正在创建window对象的属性。把
_randomGenerator = new RandomNumberGenerator();
window._randomGenerator = new RandomNumberGenerator();
这个显式声明在严格模式下是强制性的。
虽然您可以像那样模块化您的代码,但您仍然可能引入大量全局变量。通过添加_前缀,您使用了一种防御策略,但是根本不使用它们仍然更安全。
你实际上只需要一个模块模式。只要你的第一个文件是这样的:
window.module = {};
那么剩下的模块,就可以将自己注册为模块对象的属性,而不必扭曲它们的名称。
module.randomNumberGenerator = new RandomNumberGenerator();
function RandomNumberGenerator() {
...
}
那么在任何一个文件中你都可以使用这个实例。
var rng = module.randomNumberGenerator;
// ...
var number = rng.getRandomNumber();
这是可行的,但它过于复杂,除非您声明了一些数据,需要将其放入作用域以保持隔离。
对于您的示例,您可以直接创建对象,而不是使用构造函数来创建单个实例:
// 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));
}
}
如果你有一个类,如果你没有为它提供任何静态数据,你仍然不需要将它包装在作用域中:
function SomeClass() {
// ...
}
SomeClass.prototype.someMethod = function(){
// ...
}
如果您有一些类的静态数据,例如跟踪所有实例,则可以使用作用域:
var SomeClass = (function(){
var instances = [];
function SomeClass() {
instances.push(this);
}
SomeClass.prototype.getAllInstances = function(){
return instances;
}
// expose the constructor
return SomeClass;
})();
- 如何将一个模态放在一边-显示其他模态(像..这样的向导)
- 无法使用“;测试”;作为javascript中的值,但可以使用像1这样的数字
- 重用用于淡入淡出元素的代码,这样我就不会'我不必重复我的代码
- 用Javascript正则表达式检查像x.0.0这样的字符串
- 我如何才能让我的代码像在jsfiddle中一样工作
- 在保存到本地存储之前,如何修改我得到的 json 响应以使其看起来像这样
- 如何使用javascript和php检查符号,像这样
- 是否可以像这样在卸载之前写入
- 为什么 js 在像 '{}[0]' 这样的语句中忽略 '{}'
- 正确的选择器字符串是什么,可以在像这样结构的 HTML 中获取我想要的特定元素
- 我怎样才能减少这段代码 javascript 代码,这样它就不会那么重复了
- 如何像这样显示时间,例如:1秒前,1分钟前,1小时前,1个月前
- 如何使用getElementsByClassName检查输入中的值,像这样
- Javascript - 如何避免像下面给出的代码片段这样的 if 语句
- 如何在示例中构建像这样的简单图像旋转效果
- 使用哪个插件来调整图像大小,就像这样
- 为什么像这样向 JavaScript 引用类型添加方法不起作用
- 我可以像这样发送html的值$("#id").html()给后面的代码吗?
- 如何获取有关“魔法”的信息像这样的代码,用于pdf的JavaScript API
- 我可以模块化我的javascript代码像这样