什么是模块化?️
在使用Node写代码的时候,我们常常会使用module.exports来导出一个变量或函数,用require(文件名)来导入对应的变量或函数
示范:
在Node上写代码的小伙伴都知道:
先来看这段代码(hello.js)
var str = '你好';
function hello(name) {
console.log(str+','+name+'!');
};
module.exports = hello;
如果在一个js里这么写,可以利用module.exports = hello;来将hello()这个函数进行“导出”到某个地方。
然后在另一个js文件中:(main.js)
var hello =require('./hello.js');
var str = 'Hello';
hello('苏一恒');//你好,苏一恒!
通过require(文件名)来获取到被导出到hello()函数并加以调用。
此时控制台输出“你好,苏一恒!”
思考?
当我们写让浏览器加载的JavaScript时,不是通过<script>引入一堆外部js吗,那样就相当于将所有的js文件混杂到一个文件中,所有的变量都共享:
问题1:为啥str没有被覆盖?
问题2:module.exports=hello;是如何将hello暴露出去的?
问题3:require('./hello.js');是如何获取到被暴露出的hello()函数的?
解答?
问题1:为啥str没有被覆盖?
这里其实用到了闭包的原理。什么是闭包?如果你不知道,你可以先简单理解成“定义在一个函数内部的函数”,目的是读取函数内部的变量,将变量保存在内存中。
其实Node对你写的js文件进行了一个包裹:
(function () {
//你的js代码
})();
这样你的文件就变成了一个匿名内部函数,其他文件也是匿名内部函数,而函数内部的变量互不干扰,所以str就没有被覆盖了。
(function(){})()这种表达还是一种“立即执行函数(IIFE)”的语法。
问题2:module.exports=hello;是如何将hello暴露出去的?
这里其实是Node在处理你的js文件的时候,对里面的代码进行了巧妙的封装:
// 定义一个module
var module = {
id: 'hello',
exports: {}
};
var load = function (module) {
// 读取的hello.js代码:
var str = '你好';
function hello(name) {
console.log(str+','+name+'!');
};
module.exports = hello;
// hello.js代码结束
return module.exports;
};
var exported = load(module);
// 保存module,只用知道被Node保存了就行
save(module, exported);
为了讲解方便,我将hello.js代码前的代码记作A,将hello,js代码记作B,将hello.js代码后的代码记作C,
所以B代码是被夹在了A和C之间。
这一夹,Node完全按照js的正常逻辑把hello()函数保存在了某个地方,这样就能在其他地方获取到hello了,从而实现了"导出"(向外暴露)的效果。其实,Node只是单纯地进行了代码合并,巧妙的将“module.exports”这种看起来“语义化”的代码,当作一个赋值语句添加在AC模版中间。这里不得不佩服创造这种逻辑的人,点赞?!
问题3:require('./hello.js');是如何获取到被暴露出的hello()函数的?
由于Node保存了所有的module,当require()时就能将对应当module里面当exports返回,这样在另一个模块中就顺利拿到了被暴露的东西。
总结
存在即合理。
js由于太“松散自由”,被吐槽了那么多年,祸兮,福之所倚;福兮,祸之所伏。凡事各有利弊,你看这个好的特性被挖掘出来,就很容易进入潮流了,谁知道未来还有没有更新的模式被挖掘呢?自由度高,创造了条件。
个人觉得,未来js还是可以大方光彩的,作为一个前端,由衷地开心。