ToB企服应用市场:ToB评测及商务社交产业平台

标题: 彻底明白前端模块化 [打印本页]

作者: 涛声依旧在    时间: 2024-10-9 20:41
标题: 彻底明白前端模块化
模块化是一种处置惩罚复杂系统分解成为更好的可管理模块的方式,模块化开辟最终的目标是将步调划分成一个个小的结构

引入

历史


问题

早期没有模块化带来了很多的问题:比如定名辩说的问题,我们是使用 立刻函数调用表达式(IIFE) 来办理的,但也会有其他问题:

需要制定一定的规范来约束每个人都按照这个规范去编写模块化的代码,JavaScript社区为相识决上面的问题,涌现出一系列好用的规范,接下来我们逐一学习
CommonJS

CommonJS 是一种模块系统规范,告急用于在服务器端情况(如 Node.js)中管理模块。它提供了模块的界说、加载、导出机制,答应开辟者在不同模块之间共享代码。在 Node.js 中,CommonJS 是默认的模块系统,虽然现在 Node.js 也支持 ECMAScript 模块,但 CommonJS 仍旧广泛使用

exports导出

exports是一个对象,我们可以在这个对象中添加很多个属性,添加的属性会导出
  1. // a.js
  2. function add(num1, num2) {
  3.   return num1 + num2;
  4. }
  5. const message = "hello world";
  6. console.log(exports); // {}
  7. exports.add = add;
  8. exports.message = message;
  9. // main.js
  10. // const { add, message } = require("./a"); // 可以拿到文件中导出的exports对象,相当于引用赋值
  11. // console.log(add(10, 30)); // 40
  12. // console.log(message); // hello world
  13. const a = require("./a");
  14. console.log(a.add(10, 30)); // 40
  15. console.log(a.message); // hello world
复制代码
上面代码原理:

exports是一个对象,在内存中就会有个对象地址比如是0x100,那么exports就指向这个引用地址
当执行const a = require("./a")时require就会找到a模块导出的exports,把exports的引用地址赋值给a,a和exports指向了同一个对象
也就意味着你在main.js两秒后修改了message的值,两秒后在a.js中获取时会酿成你新改的值
module.exports导出

  1. // b.js
  2. function add(num1, num2) {
  3.   return num1 + num2;
  4. }
  5. const message = "hello world";
  6. // 方式一
  7. // module.exports.add = add;
  8. // module.exports.message = message;
  9. // console.log(module.exports === exports); // true
  10. // 方式二:开发中常用,module.exports赋值新对象更灵活方便
  11. module.exports = {
  12.   add,
  13.   message,
  14. };
  15. // main.js
  16. const b = require("./b");
  17. console.log(b.add(10, 20)); // 30
  18. console.log(b.message); // hello world
复制代码
上面代码原理:

module.exports和exports有什么关系呢?

我们开辟中常用的是module.exports,而且他俩还相等,那有exports另有什么意义那?

require导入

我们已经知道,require是⼀个函数,可以帮助我们引⼊⼀个⽂件(模块)中导出的对象
require的查找规则是怎么样的呢?导⼊格式如下:require(X)

加载过程


缺点


AMD规范(根本不消)

AMD告急是⽤于欣赏器的⼀种模块化规范

require.js使⽤


CMD规范(根本不消)

CMD规范也是⽤于欣赏器的⼀种模块化规范:

SeaJS的使⽤


ES Module

JavaScript没有模块化⼀直是它的痛点,所以才会产⽣我们前⾯学习的社区规范:CommonJS、AMD、CMD等,所以在 ECMA 推出⾃⼰的模块化系统时,⼤家也是很兴奋

简单使用


export关键字

export关键字将一个模块中的变量、函数、类等导出

  1. // 方式一
  2. export const message1 = "hello world1";
  3. export function add1(num1, num2) {
  4.   return num1 + num2;
  5. }
  6. export class Person1 {
  7.   constructor(name) {
  8.     this.name = name;
  9.   }
  10. }
  11. // 方式二
  12. const message2 = "hello world2";
  13. function add2(num1, num2) {
  14.   return num1 + num2;
  15. }
  16. class Person2 {
  17.   constructor(name) {
  18.     this.name = name;
  19.   }
  20. }
  21. export { message2, add2, Person2 };
  22. // 方式三
  23. const message3 = "hello world3";
  24. function add3(num1, num2) {
  25.   return num1 + num2;
  26. }
  27. class Person3 {
  28.   constructor(name) {
  29.     this.name = name;
  30.   }
  31. }
  32. export { message3, add3 as add0, Person3 as Person0 };
复制代码
import关键字

import关键字负责从别的一个模块中导入内容

  1. // 结合export中的代码学习
  2. import {
  3.   message1, // 方式一
  4.   message2,
  5.   message3,
  6.   add0 as add3, // 方式二
  7.   add1,
  8.   add2,
  9.   Person0 as Person3,
  10.   Person1,
  11.   Person2,
  12. } from "./a.js";
  13. import * as a from "./a.js"; // 方式三
  14. console.log(
  15.   message1,
  16.   message2,
  17.   message3,
  18.   add1,
  19.   add2,
  20.   add3,
  21.   Person1,
  22.   Person2,
  23.   Person3,
  24.   a.message1,
  25.   a.message2,
  26.   a.message3,
  27.   a.add1,
  28.   a.add2,
  29.   a.add0,
  30.   a.Person1,
  31.   a.Person2,
  32.   a.Person0
  33. );
复制代码
export和import结合

在开辟和封装一个功能库时,通常希望将袒露的所有接口放到一个文件中,这样方便指定统一的接口规范也方便阅读,这个时候就可以使用export和import结合使用
  1. /* util/index 通常是不编写逻辑的,在这里统一导入并导出 */
  2. // 方式一
  3. import {
  4.   message1,
  5.   message2,
  6.   message3,
  7.   add0 as add3,
  8.   add1,
  9.   add2,
  10.   Person0 as Person3,
  11.   Person1,
  12.   Person2,
  13. } from "./a.js";
  14. import { getData } from "./b.js";
  15. export {
  16.   message1,
  17.   message2,
  18.   message3,
  19.   add3,
  20.   add1,
  21.   add2,
  22.   Person3,
  23.   Person1,
  24.   Person2,
  25.   getData,
  26. };
  27. // 方式二:结合
  28. export {
  29.   message1,
  30.   message2,
  31.   message3,
  32.   add0 as add3,
  33.   add1,
  34.   add2,
  35.   Person0 as Person3,
  36.   Person1,
  37.   Person2,
  38. } from "./a.js";
  39. export { getData } from "./b.js";
  40. // 方式三:建议当有相应的文档时再这样写
  41. export * from "./a.js";
  42. export * from "./b.js";
复制代码
default⽤法

前面学习的导出都是有名字的导出(named exports):在导出export时指定了名字,在导入import时需要知道详细的名字,文件只有一个想要导出的内容并且文件名已经概括时就可以使用默认导出(default export)

import函数

import 是 静态的,这意味着在编译或打包阶段,模块依赖关系就已经确定了。JavaScript 引擎需要在脚本开始执行之前分析所有的模块和依赖项,以便优化打包、代码分割、死代码消除等操作。如果需要根据不同的条件,动态来选择加载模块,这个时候我们需要使⽤ import() 函数

  1. /* a.js */
  2. export function add(num1, num2) {
  3.   return num1 + num2;
  4. }
  5. /* validMobile.js */
  6. export default (str) => {
  7.   const reg = /^1[3-9]\d{9}$/;
  8.   return reg.test(str);
  9. };
  10. /* main.js */
  11. import validMobile from "./validMobile.js";
  12. console.log(validMobile("12345678910")); // false
  13. if (validMobile("13626068779")) {
  14.   // 结合 export
  15.   import("./a.js").then((a) => {
  16.     console.log(a.add(10, 20)); // 30
  17.   });
  18. } else {
  19.   // 结合 export default
  20.   import("./validMobile.js").then((v) => {
  21.     console.log(v.default("13626068779")); // true
  22.   });
  23. }
复制代码
import meta

import.meta是⼀个给JavaScript模块袒露特定上下⽂的元数据属性的对象,它包含了这个模块的信息,⽐如说这个模块的URL


ES Module的解析

ES Module是怎样被欣赏器解析并且让模块之间可以相互引⽤的呢?


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4