Node.js module.exports的用途是什么?您如何使用它?
我似乎找不到关于这个的任何信息,但它似乎是Node.js的一个相当重要的部分,因为我经常在源代码中看到它。
根据Node.js文档:
单元参考电流单元特别是module.exports与导出对象相同。看见src/node.js获取更多信息。
但这并没有真正的帮助。
module.exports到底做什么?一个简单的例子是什么?
Node.js module.exports的用途是什么?您如何使用它?
我似乎找不到关于这个的任何信息,但它似乎是Node.js的一个相当重要的部分,因为我经常在源代码中看到它。
根据Node.js文档:
单元参考电流单元特别是module.exports与导出对象相同。看见src/node.js获取更多信息。
但这并没有真正的帮助。
module.exports到底做什么?一个简单的例子是什么?
当前回答
模块系统的目的是什么?
它完成了以下任务:
使我们的文件从膨胀到真正的大尺寸。在开发过程中,通常很难处理包含5000行代码的文件。强制分离关注点。将代码拆分为多个文件可以让我们为每个文件指定适当的文件名。通过这种方式,我们可以很容易地确定每个模块都做什么以及在哪里找到它(假设我们制作了一个逻辑目录结构,这仍然是您的责任)。
拥有模块可以更容易地找到代码的某些部分,从而使代码更易于维护。
它是如何工作的?
NodejS使用CommomJS模块系统,其工作方式如下:
如果文件想要导出某些内容,则必须使用module.export语法声明它如果文件要导入某个内容,则必须使用require('file')语法声明它
例子:
测试1.js
const test2 = require('./test2'); // returns the module.exports object of a file
test2.Func1(); // logs func1
test2.Func2(); // logs func2
测试2.js
module.exports.Func1 = () => {console.log('func1')};
exports.Func2 = () => {console.log('func2')};
其他需要了解的有用信息:
正在缓存模块。当您在两个不同的文件中加载相同的模块时,该模块只需加载一次。第二次对同一模块调用require()时,将从缓存中取出。模块以同步方式加载。这个行为是必需的,如果它是异步的,我们无法立即访问从require()中检索的对象。
其他回答
模块将相关代码封装为单个代码单元。创建模块时,这可以解释为将所有相关函数移动到文件中。
假设有一个文件Hello.js,其中包含两个函数
sayHelloInEnglish = function() {
return "Hello";
};
sayHelloInSpanish = function() {
return "Hola";
};
只有当代码的实用程序不止一次调用时,我们才编写函数。
假设我们想将函数的实用性增加到另一个文件,比如World.js,在这种情况下,导出一个文件会变成图片,可以通过module.exports获得。
您可以通过下面给出的代码同时导出这两个函数
var anyVariable={
sayHelloInEnglish = function() {
return "Hello";
};
sayHelloInSpanish = function() {
return "Hola";
};
}
module.export=anyVariable;
现在您只需要将文件名输入World.js即可使用这些函数
var world= require("./hello.js");
请注意,NodeJS模块机制基于CommonJS模块,这些模块在许多其他实现中都受支持,如RequireJS,但也包括SproutCore、CouchDB、Wakanda、OrientDB、ArangoDB、RingoJS、TeaJS、SilkJS、curl.js,甚至Adobe Photoshop(通过PSLib)。您可以在这里找到已知实现的完整列表。
除非您的模块使用特定于节点的特性或模块,否则我强烈建议您使用导出,而不是不属于CommonJS标准的module.exports,并且其他实现通常不支持。
另一个特定于NodeJS的特性是,当您将一个引用分配给一个要导出的新对象时,而不是像Jed Watson在这个线程中提供的最后一个示例那样向其添加财产和方法。我个人不赞成这种做法,因为这打破了CommonJS模块机制的循环引用支持。它不是所有实现都支持的,Jed示例应该以这种方式(或类似的方式)编写,以提供更通用的模块:
(sayhello.js):
exports.run = function() {
console.log("Hello World!");
}
(app.js):
var sayHello = require('./sayhello');
sayHello.run(); // "Hello World!"
或使用ES6功能
(sayhello.js):
Object.assign(exports, {
// Put all your public API here
sayhello() {
console.log("Hello World!");
}
});
(app.js):
const { sayHello } = require('./sayhello');
sayHello(); // "Hello World!"
PS:看起来Appcelerator也实现了CommonJS模块,但没有循环引用支持(参见:Appcelerater和CommonJS模块(缓存和循环引用))
将程序代码划分为多个文件时,module.exports用于向模块的使用者发布变量和函数。源文件中的require()调用将替换为从模块加载的相应module.exports。
编写模块时记住
模块加载被缓存,只有初始调用评估JavaScript。可以在模块中使用局部变量和函数,而不需要导出所有内容。module.exports对象也可用作导出速记。但当返回一个单独的函数时,请始终使用module.exports。
根据:“模块第2部分-编写模块”。
module.exports属性或exports对象允许模块选择应该与应用程序共享的内容
我这里有关于module_export的视频
参考链接如下:
exports = module.exports = function(){
//....
}
导出或模块的财产。导出,例如函数或变量,将在外部公开
有一点你必须更加注意:不要覆盖导出。
为什么?
因为导出只是module.exports的引用,所以可以将财产添加到导出中,但如果覆盖导出,引用链接将断开。
很好的例子:
exports.name = 'william';
exports.getName = function(){
console.log(this.name);
}
坏例子:
exports = 'william';
exports = function(){
//...
}
如果您只想公开一个函数或变量,如下所示:
// test.js
var name = 'william';
module.exports = function(){
console.log(name);
}
// index.js
var test = require('./test');
test();
这个模块只公开了一个函数,name的属性对外是私有的。