js 模块化基础和模块规范AMD、CMD、ES6模块

举报
彭世瑜 发表于 2021/08/13 23:10:24 2021/08/13
【摘要】 一、模块基础 1、基于文件的模块化 把相关函数写在一个文件里 <script> function func1() { // ... } function func2() { // ... } </script> 123456789 缺点:污染了全局变量,无法保证不与其他模块发生变量名冲突 2、基于对象的模块化 把所...

一、模块基础

1、基于文件的模块化

把相关函数写在一个文件里

<script>
  function func1() { //   ...
  } function func2() { //   ...
  }
</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

缺点:污染了全局变量,无法保证不与其他模块发生变量名冲突

2、基于对象的模块化

把所有的模块成员封装在一个对象中

<script>
  var myModule = { name: "Tom", func: function () {},
  };
</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

优点:避免了变量污染,只要保证模块名唯一即可

缺陷:外部可以随意修改内部成员

3、基于函数的模块化

通过立即执行函数返回对象

<script>
  var myModule = (function () { var name = "Tom"; function func() {} return { name: name, sayHello: sayHello, };
  })();
</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

优点:模块外部无法修改我们没有暴露出来的变量、函数

二、JavaScript 模块规范

其中【基于函数的模块化】是模块化的基础

目前,通行的 JavaScript 模块规范主要有两种:CommonJS 和 AMD

1、Node.js 实现 CommonJS

  1. 定义模块:一个文件就是一个模块,有单独的作用域
  2. 模块输出:要导出的内容放入 module.exports 对象
  3. 加载模块:require 返回 module.exports 对象

eg:

定义模块

// a.js

function func() {
  console.log("func");
}

module.exports = {
  func: func,
};

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

加载模块

// b.js

const myModule = require("./a");

myModule.func();

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

以上方法浏览器不直接支持

2、AMD 异步模块定义

Asynchronous Module Definition

由 require.js 支持

文档:https://requirejs.org/

实现接口:

// 定义模块
define(id?, dependencies?, factory);

id:模块的标识,默认脚本文件名
dependencies:当前模块依赖的模块名称数组
factory:模块初始化要执行的函数或对象

// 加载模块
require(dependencies, callback);

dependencies: 所依赖的模块数组
callback: 前面指定的模块都加载成功后的回调函数

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

eg:

1、下载

wget https://cdn.bootcdn.net/ajax/libs/require.js/2.3.6/require.min.js

  
 
  • 1

2、helper.js 定义模块

// 模块名,模块依赖,模块的实现function
define(function () {
  return { func: function () { console.log("hello"); },
  };
});

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2、app.js 引入模块

require(["helper"], function (helper) {
  helper.func();
});

  
 
  • 1
  • 2
  • 3

3、index.html 浏览器中使用

<script src="require.min.js" data-main="app.js"></script>

  
 
  • 1

3、CMD 通用模块定义

Common Module Definition

由 Sea.js 支持

文档:https://seajs.github.io/seajs/docs/#intro

实现接口

// 定义模块
define(id?, deps?, factory)

一般不在define的参数中写依赖

factory = function(require, exports, module)
require 用来获取其他模块提供的接口:require(id)
exports 用来向外提供模块接口
module 存储了与当前模块相关联的一些属性和方法


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

eg:

1、下载

wget https://cdn.bootcdn.net/ajax/libs/seajs/3.0.3/sea.js

  
 
  • 1

2、helper.js 定义模块

define(function (require, exports, module) {
  exports.func = function () { console.log("hello");
  };
});

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

3、app.js 引入模块

define(function (require, exports, module) {
  var helper = require("helper");
  helper.func();
});

  
 
  • 1
  • 2
  • 3
  • 4

4、index.html 浏览器中使用

<script src="sea.js"></script>

<script>
  seajs.use("app");
</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

4、AMD 与 CMD 区别

  1. AMD 推崇依赖前置,在定义模块的时候就要声明其依赖的模块
  2. CMD 推崇就近依赖,只有在用到某个模块的时候再去 require

三、ES6 模块

1、ES6 模块与 CommonJS 模块的差异

差异点 CommonJS ES6
模块输出 值拷贝 值引用
机制 运行时加载 编译时输出接口
顶层 this 指向 当前模块 undefined

以下这些顶层变量在 ES6 模块之中都是不存在的

arguments
require
module
exports
__filename
__dirname

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2、模块加载

1、传统方法

<!-- 页面内嵌的脚本 -->
<script type="application/javascript">
  // module code
</script>

<!-- 外部脚本 -->
<script type="application/javascript" src="demo.js"></script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

浏览器脚本的默认语言是 JavaScript,因此 type="application/javascript"可以省略

默认情况下,浏览器是同步加载 JavaScript 脚本,执行完脚本,再继续向下渲染

2、异步加载脚本

<!-- 渲染完再执行 -->
<script src="demo.js" defer></script>

<!-- 下载完就执行 -->
<script src="demo.js" async></script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

3、ES6 加载

<script type="module" src="./foo.js"></script>
<!-- 等同于 -->
<script type="module" src="./foo.js" defer></script>

  
 
  • 1
  • 2
  • 3

eg:
模块文件 demo.js

export default function () {
  console.log("demo");
}

  
 
  • 1
  • 2
  • 3

主文件 index.html

<script type="module">
  import Demo from "./demo.js";
  Demo();
</script>

  
 
  • 1
  • 2
  • 3
  • 4

参考

  1. 前端模块化,AMD 与 CMD 的区别
  2. Module 的加载实现

文章来源: pengshiyu.blog.csdn.net,作者:彭世瑜,版权归原作者所有,如需转载,请联系作者。

原文链接:pengshiyu.blog.csdn.net/article/details/106031080

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。