【JavaScript】经典的模块化规范
模块化
什么是模块化
模块化是一种将复杂系统分解为更易管理的模块的方式。每个模块封装了特定的功能,提供使用接口,模块中的数据都是私有的,模块之间互相隔离,彼此之间互不影响。
为什么需要模块化
JavaScript语言最初设计用于浏览器的时候并没有内置的模块系统。最初我们通过<script> 标签引入文件,所有变量和函数都挂在**全局对象 window (浏览器窗口)**上。
<script src="a.js"></script>
<script src="b.js"></script>
<script src="school.js"></script>
随着node.js的出现js开始进入服务端开发,开发应用复杂度越来越高,代码量和文件数量急剧增加,加上js原有的不足,可能会引发以下问题:
- 全局污染:不同js文件有同名函数,调用函数时会产生混乱;如果 a.js 和 b.js 都有同名变量,后者会覆盖前者。
- 依赖混乱:部分js文件会与其他js文件有依赖关系,所以必须按照一定的顺序进行引入,引入的过程可能产生混乱。
- 数据安全问题:所有模块成员仍暴露在全局即window上,外部可以直接修改内部数据。
模块化规范有CommonJS、AMD、CMD、ES6模块化,本文只讲较为常用的两个规范,CommonJS和ES6模块化。
两个经典的模块化规范
CommonJS
CommonJS最早是当时在雅虎工作的Kevin Dangoor发起的一个社区项目(非官方模块化规范),在node.js流行的基础上发展起来,所以其规范也主要用于node.js服务器端。
导出数据的方法
该规范有两种导出数据的方式:
const name = 'Harvard'
const location1 = 'Cambridge, MA'
function getTel (){
return '(617) 495-1000'
}
function getCity(){
return 'Cambridge'
}
// 方法一
exports.name = name
// 方法二
module.exports = {name,getTel}
用 require() 导入
关于js文件的空对象
深入探究js文件的空对象,有助于理解CommonJS数据的导出及其导出过程中可能引发的问题。
每个模块,一开始都有this关键字、exports、modules.exports共同指向同一个空对象,该对象是js文件要导出的数据。
在每个模块文件开头,Node.js 实际上执行了类似这样的代码:
var exports = module.exports;
exports 是 module.exports 的一个引用,this 在模块作用域中也指向 module.exports,module.exports 是真正的导出目标。所以,无论如何修改导出对象,最终导出的是module.exports的值。
JS模块的作用域
js模块在执行时是被包裹在内置函数中执行的,每个模块有自己的作用域。
当你运行如下代码:
console.log(arguments.callee.toString())
会得到
function (exports, require, module, __filename, __dirname){
// 这里是作用域,内容是模块中写的代码
// ...
}
这是因为 Node.js 会把每个模块文件包装在一个函数中执行。
ES6模块化
ES6 (ECMAScript 2015) 是JavaScript 的官方标准规范,浏览器和node.js服务端都支持。
ES6 是正式的 ECMA-262 标准
标准号: ECMA-262 6th Edition
官方名称: ECMAScript 2015 (ES2015)
导出数据或执行代码的方法
- 分别导出 exports
- 统一导出 export {…}(类似于对象的结构)
(分别导入和统一导入可以用{ }里的对象进行接收) - 默认导出 export default {…}
提交的是值(default:…)而不是对象,也可以是自己设置的对象(可设置键值对)。
在import时可以随意命名一个对象接收 - 命名导入:在需要导入的文件中直接import
- 动态导入:触发一定条件后导入,如点击事件。
- import可不接收任何数据,只触发引用的js中的函数。
浏览器运行ES6模块
当在浏览器中运行ES6模块时,js文件需要以模块化的方式被引入到html,这时type属性需要改为module。
<script type="module" src="./school.js"></script>
引入模块后,模块的内容都在模块中运行,不会污染全局。
node.js运行ES6模块
两种方法:
- 改文件后缀.mjs(不推荐)
- 在package.json中设置
{
"name": "...",
"version": "...",
"type": "module",
"main": "src/index.js",
"scripts": {
"start": "...",
"dev": "..."
},
"dependencies": {
"lodash": "..."
}
}
index.js为对应的ES6模块。
模块辨析——数据引用问题
CommonJS规范导出的数据是值的拷贝。
ES6规范导出的数据是值的引用,与原文件数据共用同个内存,即指向同一个对象,但导入的变量是只读绑定,不能直接赋值。
觉得不错可以三连支持一下,欢迎讨论纠错~
3117

被折叠的 条评论
为什么被折叠?



