theme: juejin
持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第30天,点击查看活动详情
每天3分钟,重学ES6-ES12文章汇总
前言
今天开始和大家一起系统的学习ES6 ,每天3分钟,用一把斗地主的时间,重学ES6 ,前面我们介绍了模块化的历史,今天介绍模块化处理方案
CommonJS
CommonJS规范和Node关系
- common Js 是一个规范,指出是在浏览器以外的地方,可以简称为CJS
- Node 是commonJs 在服务器端一个具体有代表性的一个实现
- webpack打包工具具备对commonJS的支持和转换
- node 中每一个js文件都有是一个单独的模块
- 包括CommonJS规范的核心变量:exports,module.exports, requrie
导出方式
exports.a
module.exports ={a:a}
代码语言:javascript复制// 源码
module.exports = {}
exports = module.exports
//最终能导出的一定是module.exports()
内部原理
代码语言:javascript复制// main.js
const why = require("./why.js")
console.log(why)
setTimeout(() => {
console.log(why.name)
why.name = "james"
}, 1000)
// why.js
const info = {
name: "why",
age: 18,
foo: function() {
console.log("foo函数~")
}
}
setTimeout(() => {
// info.name = "kobe"
console.log(info.name)
}, 2000)
module.exports = info
两个文件 执行node main.js 输出结果为
{ name: 'why', age: 18, foo: [Function: foo] } why james
先打印why对象,然后打印why 修改why name 打印 james
由此可见,require 引入的文件是加载时执行
require执行细节
require是一个函数,可以帮助我们引入一个文件(模块)中导出的对象。
require(X)
查找规则
- 1.如果X是node的一个核心模块,如http path 则直接返回核心模块,并停止查找
- 2.如果X是一个路径
- 2.1.将X当作是文件名在对应的目录下查找
- 如果有后缀名,按照后缀名的格式查找对应的文件
- 如果没有后缀名,会按照顺序
- 直接查找文件X > 查找X.js文件 > 查找X.json文件>查找X.node文件
- 2.2.如果没有找到对应的文件,将X作为一个目录
- 查找目录下的index文件
- 查找X/index.js文件>查找X/index.json文件>查找X/index.node文件
- 3.非路径也非核心模块(第三方包)
- 每层级依次去寻找node_modules 如果都没找到,那么报错:not found
模块的加载过程
- 结论一:模块在被第一次引入时,模块中的js代码会被运行一次
- 结论二:模块被多次引入时,会缓存,最终只加载(运行)一次
- 这是因为每个模块对象module都有一个属性:loaded。
- 为false表示还没有加载,为true表示已经加载;
- 结论三:如果有循环引入,Node采用的是深度优先算法,寻找模块
CommonJS规范缺点
- CommonJS加载模块是同步的:
- 同步的意味着只有等到
对应的模块加载完毕,当前模块中的内容才能被运行
; - 这个在服务器不会有什么问题,因为服务器
加载的js文件都是本地文件
,加载速度非常快;
- 同步的意味着只有等到
- 如果将它应用于浏览器呢?
- 浏览器
加载js文件需要先从服务器将文件下载下来
,之后再加载运行
; - 那么采用
同步的就意味着后续的js代码都无法正常运行
,即使是一些简单的DOM操作
;
- 浏览器
- 所以在浏览器中,我们通常不使用CommonJS规范:
- 当然在webpack中使用CommonJS是另外一回事;
- 因为它会将我们的代码转成浏览器可以直接执行的代码;
- 在早期为了可以在浏览器中使用模块化,通常会采用AMD或CMD:
- 但是目前一方面现代的浏览器已经支持
ES Modules
,另一方面借助于webpack等工具可以实现对CommonJS或者ESModule代码
的转换; AMD和CMD已经使用非常少了
,所以这里我们也不展开介绍了。
- 但是目前一方面现代的浏览器已经支持