前端的模块化(闭包,CommonJS,AMD,CMD和ES6)

前端发展史

所有功能的出现都是为了解决一个相对应的问题。
在前端发展的浩荡时间里,随着浏览器和电脑设备的发展,前端项目越来越复杂,项目目录越来越大,出现了各种JS文件,但是在各个JS文件引用之间,总是有可能出现函数声明重名或变量声明重名。因此为了解决这个问题,相应提出了解决方案:前端模块化。
在这里插入图片描述

一,闭包,立即执行函数(IIFE)实现前端模块化

在最一开始大家只是用闭包的方式来实现前端模块化,在闭包将函数中声明和实现,封装在_Module对象中,再挂载在全局作用域(window或global)身上,来基本实现前端的模块化。

let global = (function () {
  return globalThis || window || global;
})();

(function (global) {
  let x = 1;
  function add(a, b) {
    return a + b;
  }
  function subtract(a, b) {
    return a - b;
  }

  return (global._Module = {
    x,
    add,
    subtract,
  });
})(global);

global._Module.x = 2;
console.log(global._Module.x);

二,CommonJS标准

在这前端发展举步维艰的时刻,CommonJS标准应运而生
node实现了commonJS:

(1),介绍

Node 应用由模块组成,采用 CommonJS 模块规范。每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。在服务器端,模块的加载是运行时同步加载的;在浏览器端,模块需要提前编译打包处理。

(2),api

  • 暴露模块:module.exports = value或exports.xxx = value
  • 引入模块:require(xxx),如果是第三方模块,xxx为模块名;如果是自定义模块,xxx为模块文件路径

使用module.exports 导出module2.js文件想要暴露的方法和属性

// module2.js

let SayName = function (Person) {
  console.log("Hello, my name is " + Person.name);
};

let SayAge = function (Person) {
  console.log("I am " + Person.age + " years old");
};

let SayCity = function (Person) {
  console.log("I live in " + Person.city);
};

module.exports = { SayName, SayAge, SayCity };

使用require引入别module2.js导出的方法

// module1.js
let { SayAge, SayName, SayCity } = require("./module2.js");
let Person = {
  name: "John",
  age: 30,
  city: "New York",
};
SayCity(Person);
SayAge(Person);

(3),特点

  • 所有代码都运行在模块作用域,不会污染全局作用域。
  • 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
  • 模块加载的顺序,按照其在代码中出现的顺序。

三,AMD和CMD规范

AMD

Asynchronous Module Definition,中文名是异步模块定义的意思。它是一个在浏览器端模块化开发的规范。requireJS实现了这个规范

CMD

SeaJS 在推广过程中对模块定义的规范化产出(国产)。

总结:

不过随着ES6的出现,这两个规范也逐渐不再使用。一些比较老一点的项目还可能在使用这两个

ES6 规范

(1),介绍

在2016年 Ecm提出了ES6规范,在ES6规范中实现了前端的模块化,

(2),api

  • import aaa , { bbb , ccc } from ‘’ ./xxx "
    aaa:是export default一个文件只能导出一个
    bbb,ccc:是正常 export导出
    xxx:是引用的文件夹目录

到处方式有很多种:

  • export let aaa = [ function(){} || value]
  • export aaa
  • export default aaa;
// module2.js
export let add = function (a, b) {
  return a + b;
};
export let subtract = function (a, b) {
  return a - b;
};
const log = function (a) {
  console.log(a);
};
export default log;

在浏览器中使用 type=“module” 引入其他文件注意:

  • 必须加上type=“module”,这样浏览器才会将该使用ES6去执行,否则默认是传统脚本
  • module是默认不支持同源加载的,需要启动一个服务器,解决跨域问题
// 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>
  </head>
  <body>
    <script type="module">
      import log, { add, subtract } from "./module2.js";
      console.log(add(1, 2));
      console.log(subtract(1, 2));
      log(1);
    </script>
  </body>
</html>

(3),特点

ES6模块中的值属于【动态只读引用】。

  • 对于只读来说,即不允许修改引入变量的值,import的变量是只读的,不论是基本数据类型还是复杂数据类型。当模块遇到import命令时,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。
  • 对于动态来说,原始值发生变化,import加载的值也会发生变化。不论是基本数据类型还是复杂数据类型。
  • 循环加载时,ES6模块是动态引用。只要两个模块之间存在某个引用,代码就能够执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值