通过Anuglar Material串串学客户端开发 - NodeJS模块机制之Module.Exports

时间:2021-09-04 15:15:18

module.exports

前文讲到在Angular Material的第二个编译文件docs/gulpfile.js中却看到了一个奇怪的东西module.exports 那么module.exports是什么东西呢?

一直以来,javascript最大的诟病就是全局变量,这也成为大型应用开发的最大阻碍。因此,很多人使用了很多方式来解决这个问题。如模块模式(Module Pattern), 而node.js这实现了模块装载系统,来解决组件实现的基本问题。

自从开始研究前端,我也几个相关的关键词在眼前晃荡, require() exports等等。当时,因为注意力在其他方面,一直也没下决心研究清楚。 就如下面文章中所讲:

作为开发人员常常面临这样的困境:当我们使用不熟悉的代码(库)时,我们究竟要花多少时间来研究它的原理和实现,这个研究又要有多深呢?经典答案就是,学习到足够可以开始写代码就可以了,等到时间容许在进一步深入研究。

那么现在就是深入研究 module.exports的时候了!

Node.js如何定义和使用模块

传统js文件

这里是一个简单的js文件,greeting.js,它的功能一看就明白:

//greetings.js
sayHelloInEnglish = function() {
return "Hello";
}; sayHelloInSpanish = function() {
return "Hola";
};
这里有两函数也就是两个功能。

用模块封装简单js文件

i> 想象该文件第一行有以下代码(是的,想象)

// var exports = module.exports ={};

ii> 把任何要重用(导出)的函数,赋值给exports

exports.sayHelloInEnglish = function() {
return "Hello";
};
exports.sayHelloInSpanish = function() {
return "Hola";
};

iii> 以上的结果相当于做了以下的事情

module.exports = {
sayHelloInEnglish = function() {
return "Hello";
}; sayHelloInSpanish = function() {
return "Hola";
};
};

这个方式看上去有点怪异,之后可以做更进一步的解释。在这之前,可以透露一点小道消息。 Typescript定义模块的语法就感觉自然多了:

module namespace {
exports function sayHelloInEnglish = function() {
return "Hello";
};

而用tsc转译以后,他就会变成上面的node.js语法。

什么是Typescript? OK,以后有时间再深入吧? (听起来怎么这么耳熟?)

导入/使用模块

我们准备在main.js中导入和使用greetings.js中的所有函数。

i> 关键词require

require是nodejs用来导入模块的关键词。想象一下require的定义如下 (怎么又是想象?)

var require =function(path){
//....
return module.exports;
};

ii> 导入greetings.js

//main.js
var greetings = require("./greetings");

想象一下以上代码等价于你的代码做了以下事情:

//main.js
var greetings = {
sayHelloInEnglish = function() {
return "Hello";
}; sayHelloInSpanish = function() {
return "Hola";
};
};

iii> 现在我么就可以重用greetings.js的功能了

//"Hello"
greetings.sayHelloInEnglish(); // "Hola"
greetings.sayHelloInSpanish();

警告:

正因为nodejs的这种模块机制,如果不小心给module.exports重新赋给了一个全新的对象,会导致不可预期的问题。

如:

//greetings.js
//var exports=module.exports = {};
exports.sayHelloInEnglish = ...
exports.sayHelloInSpanish = ...
/*
重新赋值module.exports
*/
module.exports= "Bonjour";

这时候,在main.js中我们在调用`greetings.sayHelloInEnglish()'就会出错。

下一步:进阶研究require()的工作原理。