node.js模块化(module.exports/exports/require)

基本概念

在Node环境中,一个.js文件就称之为一个模块(module)。使用模块可以避免函数名和变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中,因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。module.exports、exports(相当于module.exports的一份引用) 导出,require导入。

使用场景

首先个人比较喜欢使用module.exports = {key: value}形式来进行模式导出,直接将一个{}对象赋值给module.exprots,这样封装工具类和全局变量都比较方便,在引入的地方,拿到的直接就是一个key-value结构的对象,使用起来也十分方便。

module.exports VS exports

相信很多人对于module.exports和exports的比较相对模糊,甚至很容易搞混。下面简单说一下,如何区分二者:
首先,node.js实现“模块”功能的奥妙在于JavaScript是一种函数式编程语言,它支持闭包。如果我们把一段JavaScript代码用一个函数包装起来,这段代码的所有“全局”变量就变成了函数内部的局部变量。简单说一下node.js模块实现原理:
我们编写一个hello.js代码:

var s = 'Hello';
var name = 'world';

console.log(s + ' ' + name + '!');

Node.js加载了hello.js后,它会把代码包装一下,变成这样执行:

(function () {
    // 读取的hello.js代码:
    var s = 'Hello';
    var name = 'world';

    console.log(s + ' ' + name + '!');
    // hello.js代码结束
})();

当你调用module.exports时,node.js将会做下面这些事情:

// 准备module对象:
var module = {
    id: 'hello',//模块编号 在你require引用的时候匹配索引使用
    exports: {}//声明一个空对象,用于存放你将要导出的函数、变量、或对象
};
var load = function (module) {
    // 读取的hello.js代码:
    function greet(name) {
        console.log('Hello, ' + name + '!');
    }
    
    module.exports = greet;
    // hello.js代码结束
    return module.exports;
};
var exported = load(module);
// 保存module:
save(module, exported);

可见,变量module是Node在加载js文件前准备的一个变量,并将其传入加载函数,我们在hello.js中可以直接使用变量module原因就在于它实际上是函数的一个参数:

module.exports = greet;

通过把参数module传递给load()函数,hello.js就顺利地把一个变量传递给了Node执行环境,Node会把module变量保存到某个地方。

由于Node保存了所有导入的module,当我们用require()获取module时,Node找到对应的module,把这个module的exports变量返回,这样,另一个模块就顺利拿到了模块的输出:

var greet = require('./hello');

以上是Node实现JavaScript模块的一个简单的原理介绍。
总结:
通过以上介绍,不难看出module是node.js自己主动为每个.js文件声明的一个变量,同时这个变量拥有两个参数,一个是索引id,一个是命名为exports的对象变量,exports用于存放用户导出的变量或属性。我们在对外导出时要做的就是:以key-value键值对的形式往module变量下的exports对象里面添加需要导出的变量或属性,由于我个人比较懒,懒得每次像下面这样一个一个的导出:

function hello() {
    console.log('Hello, world!');
}

function greet(name) {
    console.log('Hello, ' + name + '!');
}

module.exports.hello = hello;
module.exports.greet = greet;

所以,比较喜欢直接简单粗暴的声明一个对象直接把exports原有的{}对象给覆盖掉,变成下面这样:

module.exports = {
	function hello() {
    	console.log('Hello, world!');
	}

	function greet(name) {
	    console.log('Hello, ' + name + '!');
	}
};

现在,把module.exports给说清楚了,再说一下exports吧,估计你也猜到了,它其实就是module.exports的一份引用而已。为了帮你少写一个module.,可以理解为一个语法糖。个人觉得还是使用module.exports的好一些,最起码你在读完这篇文章,每次写module.exports时,可以帮你回忆一下module的由来以及exports作用。
至此,node.js的模块化结束。下一篇会写:JS ES6中export和import详解
致谢:本文灵感来源于廖雪峰老师的官方网站,想深入了解的同学,可以转战于老师官网:
https://www.liaoxuefeng.com/wiki/1022910821149312/1023027697415616

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值