前端模块化的演变

前言

模块化相关的关键字有很多,比如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


 

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值