前言
模块化相关的关键字有很多,比如IIFE(立即执行函数)、AMD、CMD、commonjs、ES module、umd等等,这些关键字有什么关系呢,都是做什么的呢
什么是模块化
直白的理解就是一个js文件内部形成自己的作用域,内部定义多个变量,当js文件相互引用时,文件内部变量,不相互影响,模块化的实现依托于作用域
什么是作用域
在const、let出现之前,js的作用域只有全局作用域和函数作用域两种,函数之间的嵌套用法又形成了作用域链(内部函数查找变量会往上一层一层查找,直到全局作用域)和闭包这两个知识点
不使用模块化
js文件内部变量命名要避免重名(很难避免),如果出现重名,后引入的js变量会覆盖先引入的js变量
示例:
a.js
var name = '我是a.js'
function printName () {
console.log(name)
}
b.js
var name = '我是b.js'
// xxx 其他逻辑代码
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./a.js"></script>
<script src="./b.js"></script>
<!-- <script src="./b.js"></script>
<script src="./a.js"></script> -->
</head>
<body>
</body>
<script>
printName()
</script>
</html>
两个文件都定义了name变量,后引入文件的name变量会覆盖了先引入的name变量
IIFE方式实现模块化
IIFE(立即执行函数)的方式,本质是借助函数的独立作用域和闭包现象,实现变量的私有化,不受外部变量影响,同时也不影响外部变量(主动暴漏出的变量除外)
示例:
a.js
(function (window) {
var name = '我是a.js'
function printName () {
console.log(name)
}
// 指定需要对外暴露的变量,赋值到window,命名需要注意避免像普通变量一样通用化
window.printName = printName
})(window)
b.js
var name = '我是b.js'
// xxx 其他逻辑代码
function printNameB () {
console.log(name)
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 验证不被外部变量影响 -->
<script src="./a.js"></script>
<script src="./b.js"></script>
<!-- 验证内部变量不影响外部 -->
<!-- <script src="./b.js"></script>
<script src="./a.js"></script> -->
</head>
<body>
</body>
<script>
// IIFE不被外部变量影响
printName()
// IIFE内部变量不影响外部
// printNameB()
</script>
</html>
AMD、CMD、commonjs
前端的模块化在ES module出来之前是没有统一的规范标准的,随着前端的发展,项目越来越复杂,模块化的实现势在必行;所以在js宿主环境(node环境和浏览器)分别产生了自己的标准;
node环境:commonjs
浏览器环境:AMD、CMD
commonjs规范在使用node开发服务器或者webpack和babel插件时会经常用到,这里不做解释
基于AMD和CMD规范的具体模块化实现requirejs和seajs,我自己都没有用过,不好乱说
可以参考下这个链接:
https://www.cnblogs.com/AnnieShen/p/6024848.html
ES module
ES module规范的提出,为模块化的实现提出了统一的标准,但是标准的提出从实现的角度是超前的,作为宿主环境不管是浏览器还是node,需要实现ES module的标准,肯定还是需要很长时间的版本迭代,问题来了,统一的标准还未实现,前端工程化打包出来的产物以哪一个模块化为准呢
UMD
umd 全称 Universal Module Definition,通用模块规范,umd其实不是规范,应该说是一种兼容模块化规范的方式,根据判断当前宿主环境支持哪种模块规范,就使用哪一种规范。
webpack打包指定umd格式产物示例:
!(function (e, o) {
// 判断commonjs标准
if ("object" == typeof exports && "object" == typeof module)
module.exports = o();
// 判断AMD和CMD标准
else if ("function" == typeof define && define.amd) define([], o);
else {
// 判断ES module,ES module不支持,挂在全局变量self(浏览器环境指向window, node环境指向global)
var t = o();
for (var f in t) ("object" == typeof exports ? exports : e)[f] = t[f];
}
})(self, () =>
(() => {
"use strict";
var e = {};
((e) => {
"undefined" != typeof Symbol &&
Symbol.toStringTag &&
Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }),
Object.defineProperty(e, "__esModule", { value: !0 });
})(e);
return console.log("dog"), console.log(18), e;
})()
);
demo地址
https://github.com/wufeng123456/module-demo/tree/master/umd_module