JavaScript 模块化
JavaScript 的历史问题
背景
JavaScript 在一开始诞生的时候只是用来网页脚本的开发,其实没有模块化和命名空间的概念。
JS 的模块化需求日益增长。
幼年期:无模块化
模块化思维的萌芽。
- 需要在页面中加载不同的 js:动画库,表单库,格式化工具
- 多种 js 文件被分在了不同的文件中
- 不同的文件又被同一个模版所引入
我们的解决方案是,在一个 html
中,引入不同的 script
,这样实现了一个模版引入多个不同的 js。
这个其实也是有意义的,可以认为是 js 模块化的第一步。
这里补充一下 script
标签的三个参数:
- normal:遇到标签,停止往下解析,下载且执行 JavaScript
- async:解析到标签开始异步下载,下载完之后立即执行,并且会阻塞渲染,然后继续执行
- defer:解析到标签开始异步下载,继续解析
(分别对应:normal,defer,async)
依然存在的问题:
- 兼容性
- 问题方向:浏览器渲染原理、同步异步原理、模块化加载原理
- 污染全局作用域:不易于大型项目的开发和多人项目的合作
成长期:模块化初心 IIFE
作用域的把控
let count = 0
const increase = () => {
count++
}
const rest = () => {
count = 0
}
increase()
rest()
(
// 利用立即执行行数
() => {
let count = 0
const increase = () => {
count++
}
const rest = () => {
count = 0
}
increase()
rest()
}
)()
这样我们使用了 IIFE module 实现了模块和外部之间的隔离。
成熟期
CJS - commonjs
nodejs 制定的标准。
- 特征:通过 module + export 去对外暴露接口
- 通过 require 去调用其他的模块,同步加载
模块组织方式:
main.js
// 引入部分
const dependecyModule1 = require('./dependecyModule1')
const dependecyModule2 = require('./dependecyModule2')
// 核心逻辑
let count = 0
const increase = () => count++
const reset = () => count = 0
// 暴露接口部分
export.increase = increase
export.reset = reset
// 或者统一暴露
module.exports = {
increase,reset
}
使用
const {increase, reset} = require('main.js')
commonjs 为每一个模块提供了一个 exports 变量,指向 module.exports,相当于在每一个模块代码的头部写了一行:
var exports = module.exports
exports 和 module.exports 指向同一个内存空间,module.exports 是真正的暴露对象。exports 是 module.exports 对象的引用。
commonjs 的特点:
- 使用同步加载的方式,适用于服务端,因为服务端的代码阻塞用户无法感知,而前端的阻塞会非常影响体验
- 所有的代码都运行在某块作用域中,不会影响全局
- 模块可以多次加载,但是只是第一次会下载,后面用的都是缓存
- 模块加载的顺序就是代码出现的顺序
AMD(Asynchronous Module Definition)
采用异步加载的方式加载模块,模块的加载不影响后面语句的运行,所有依赖这个模块的语句都会被写在一个回调函数中,等待加载完成之后,这个回调函数才会执行。
最热门的一个库就是 require.js
,它是一个 JavaScript 模块化框架。
requirejs(["helper/util"], function(util) {
//This function is called when scripts/helper/util.js is loaded.
//If util.js calls define(), then this function is not fired until
//util's dependencies have loaded, and the util argument will hold
//the module value for "helper/util".
});
CMD(Common Module Definition)
通用加载模块
常见的库就是 sea.js
UMD(Universal Module Definition)
UMD是AMD和CommonJS的糅合。
UMD的实现很简单:
- 先判断是否支持Node.js模块(exports是否存在),存在则使用Node.js模块模式。
- 再判断是否支持AMD(define是否存在),存在则使用AMD方式加载模块。
- 前两个都不存在,则将模块公开到全局(window或global)。
ES6 模块化
编译时去顶模块的依赖关系,原生支持。
标签:exports,const,模块化,JavaScript,js,模块,加载 From: https://blog.csdn.net/weixin_54252035/article/details/136880817