JS模块化

js早期的模块化是分为不同的外部文件,通过script标签导入同一个文件

<script src="test.js"></script>
<script src="test.js" defer></script>
<script src="test.js" async></script>

在这里插入图片描述
总结:
普通 - 解析到标签,立刻pending,并且下载执行
defer - 解析到标签,开始异步下载,解析完成之后开始执行
async - 解析到标签,开始异步下载,下载完成后立刻执行并阻塞原解析,执行结束后,继续解析

/**简单模块 */
let count = 0; //全局作用域,模块1中操作count,模块2中的count值会发生变化
//模块1
const add = () => count++;
//模块2
const subtraction = () => count--;

问题出现:污染全局作用域,不利于大型项目的开发以及多人团队共建

IIFE

//通过函数创建独立作用域
(function () {
  let count = 0; //定义在函数内部,只在当前函数中使用
  const add = () => count++;
})()
 /* 依赖其他模块的IIFE */
(function (exports, lodash) {
    //主流程
    const count = 0;
    const add = () => count++;
    //外部其他模块
    const sum = () => lodash.debounce(add, 300);
    exports.sum = sum;
    return exports;
  }
)({}, lodash);
/* 早期jquery的依赖处理 => IIFE + 传参调配
 * 实际上,传统框架利用一种揭示模式的写法*/
const iifeModule = (function (exports, $) {
  /*主流程*/
})({}, jquery);
/*实际执行处理*/
(function (thisValue, exports, require, module) {
  const depModule1 = require("./dependecncyModule1");
  const depModule2 = require("./dependecncyModule2");

  // 业务逻辑……
}).call(thisValue, exports, require, module);

// 部分开源源码,分别传入全局、指针、框架作为参数
(function (window, _, undefined) {
  // 业务逻辑……
})(window, lodash);
// window
// 1. 避免全局变化 | 全局作用域转化为局部的时候,提升效率
// 2. 编译时候优化压缩 (function(c){c}(window))
// lodash
// 1. 独立定制复写,保障稳定
// 2. 防止全局工具的全局污染
// undefined
// 防止被重写

CJS规范 - common.js(node.js制定)
特征:通过module + export去对外暴露接口;通过require进行其他模块的调用
优点:CJS率先在服务实现了从框架层面解决依赖、模块化的问题
缺点:针对的是服务端,对于异步依赖没有很友好地处理解决

const lodash = require("lodash");
let num = 0;
const increase = () => num++;
const sum = () => lodash.debounce(increase, 300);
exports.sum = sum;

AMD规范 - require.js
define(id?,dependencies?,callback)
id为定义模块的名字,如果没有为当前脚本文件名
dependencies为该模块依赖的模块数组,传入是一个数组,数组中的值是callback参数
优点:解决了浏览器中异步加载模块,可以并行加载多个模块
缺点:会有引入成本,缺少考虑按需加载

// 定义一个模块
define("module1", ["jquery", "./module2"], function ($, module2) {
  return {
    start: function () {
      $("body").animate({ margin: "200px" });
      module2();
    },
  };
});
// 载入一个模块
require(["./module1"], function (module1) {
  module1.start();
});

//定义有依赖的模块(逻辑外壳封装:可以将外部模块整合成自己的模块导出)
define(["exports", "lodash"], function (exports, _) {
  const log = () => console.log("hi");
  const myLog = () => _.debounce(log, 1000);
  exports.myLog = myLog;
});

//定义没有依赖的模块
define(function () {
  return "模块";
});

问题:怎么同时兼容AMD和CJS

/* 1.区分CJS和AMD
 * 2.module & module.exports
 * 3.define */
/*UMD实现方式*/
(function (param) {
  /** ......code */
})(
  typeof module === "Object" && module.exports && typeof define !== "function"
    ? (factory) => (module.exports = factory(require, exports, module)) //CJS
    : define //AMD
);

ESM

import { debounce } from "lodash";
const dlog = () => debounce(log, 300);
export { dlog };
// 异步加载
import("xxx").then((a) => {
  // ...
});

模块化可以将无数模块进行随意组装,隔离每个模块的逻辑和作用域,扩展共同协作的方便程度

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值