CommonJS与ESModule原理学习

69 阅读2分钟

通过相关面试题来学习

模块化是如何产生?解决了什么问题?

存在全部污染依赖管理混乱的问题 比如 一个C.js文件引入了 2个js模块 A.js B.js A中有个name变量 b中有个name 函数 在C中调用name 但是变成了name函数 这就是全局污染 当然通过匿名函数自执行形成独立作用域能解决 但是,这又带来了新的问题:

我必须记得每一个模块中返回对象的命名,才能在其他模块使用过程中正确的使用 代码写起来杂乱无章,每个文件中的代码都需要包裹在一个匿名函数中来编写 在没有合适的规范情况下,每个人、每个公司都可能会任意命名、甚至出现模块名称相同的情况

CommonJS规范

因此产生了CommonJS规范。CommonJS规范特点如下

  1. 每个js文件都是一个独立的模块
  2. 模块中包含核心变量 exports module.exports require
  3. 使用核心变量进行开发
const name = "zhoudequn"; 
const age = "18"; 
module.exports = { name, age };
//或者: 
exports.name = "zhoudequn"; 
exports.age = "18"; 
//在b.js中引用导出的变量 
const { name, age } = require("./a.js"); 
console.log( name , age )

CommonJS原理

举个例子 写一个name.js 如下

module.exports="zhoudequn"

再写一个main.js 如下

let author=require('./name.js')
console.log('author',author)

然后写一个html 引用main.js 当然在浏览器直接运行会报错的

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>commonjs</h1>
    <script src="./引用main.js"></script>
</body>
</html>

但是如果你写成如下的yuanli.js代码 再引入yuanli.js就不会报错了

var modules = {
    "./name.js": () => {
      var module = {};
      module.exports = "zhoudequn";
      return module.exports;
    },
  };
  const require = (modulePath) => {
    return modules[modulePath]();
  };
  
  let author = require("./name.js");
  console.log(author, "author");

ESModule规范

ESModule规范 借鉴了CommonJS规范 特点 使用import关键字引入模块 export导出模块

/**
 * 导出
 */
 export * from 'module'; //重定向导出 不包括 module内的default
 export { name1, name2, ..., nameN } from 'module'; // 重定向命名导出
 export { import1 as name1, import2 as name2, ..., nameN } from 'module'; // 重定向重命名导出
 export { name1, name2, …, nameN }; // 与之前声明的变量名绑定 命名导出
 export { variable1 as name1, variable2 as name2, …, nameN }; // 重命名导出
 export let name1 = 'name1'; // 声明命名导出 或者 var, const,function, function*, class
 export default expression; // 默认导出
 export default function () { ... } // 或者 function*, class
 export default function name1() { ... } // 或者 function*, class
 
 /**
  * 导入
  */
 import defaultExport from "module"; // 默认导入
 import { a, b, c } from "module"; //解构导入
 import defaultExport, { a, b, c as newC } from "module"; //混合导入
 import * as name from "module"; //混合导入
 var promise = import("module"); //动态导入(异步导入)

参考文章

juejin.cn/post/714736…