前端系列-2 模块化CommonJs+AMD+CMD+ES6

模块化

js中, 一个文件就是一个模块,模块化可以提高代码利用率而减少重复代码,将相同的逻辑维护在一个模块中,分而治之,提高代码的可维护性;另外,模块化的出现可以在工程中引入第三方模块,极大提高开发效率。
在模块化出现前,只能通过<script>标签在html中导入,并根据依赖控制导入顺序。CommonJS出现后,模块化技术不断发展,目前主流的js模块化规范有CommonJS, AMD/CMD以及ES6等模块系统,按照模块化的发展可排序为: CommonJS -> AMD/CMD -> ES6.
CommonJS用于服务端,AMD/CMD用于浏览器端,ES6是服务端和浏览器端通用的模块解决方案。

1.CommonJS规范

CommonJS规范是NodeJs默认的模块化的规范,适用于服务器端,不适用于浏览器端(理由在后面介绍).

在CommonJS中, 每个js文件就是一个模块,有自己的作用域:文件内定义的变量、函数、类都是私有的,其他模块不可见;可以通过module.exports和require组合的方式实现跨模块访问。

1.1 module对象

module.exports = {// 可以导出内部的变量、方法等
}

module变量是一个对象,表示当前模块;有一个exports属性,表示模块对外输出的值。
module对象除了这个exports属性外,还有以下属性:
[1] id 模块的标识符,带有绝对路径的模块文件名;
[2] filename: 模块的文件名,带有绝对路径;
[3] parent: 返回一个对象,调用该模块的对象;
[4] loaded:boolean,表示该模块是否加载完成;
[5] children:数组,该模块内用到的其他模块;

1.2 全局函数require

一般而言,导出是为了导入,不然导出就没有了意义。CommonJS规范通过require方法进行模块的导入.

// 引用自定义的模块时,参数包含路径,可省略.js
var math = require('./math');// 引用核心模块时,不需要带路径
var http = require('http');

require是加载模块,并给导入的模块定义名称。
require基于缓存加载模块,所有加载的模块都会缓存在require.cache中,之后再次加载会直接从缓存中读取(每个模块只会被加载一次)。require加载返回的对象为module.exports属性对象。如果被加载的模块没有给exports属性对象赋值,则加载后返回的对象为空对象{}。

1.3 案例

// entry.js
var myModule = require("./module.js")
console.log(myModule)---// module.js
var num = 1
function addNum(val){return num + val
}
module.exports = {num,addNum
}

运行结果如下:

{num: 1, addNum: ƒ}

表示myModule对象包含一个属性值num=1,和一个addNum函数。

// entry.js
var myModule = require("./module.js")
console.log(myModule)---// module.js
var num = 1
function addNum(val){return num + val
}

运行结果如下:

{}

表示myModule对象为空对象。

1.4 特点

CommonJs同步加载模块,即后面的模块需要等待前面的模块加载完成。对于服务器端,模块文件存在与本地文件系统,不存在问题。浏览器需要从服务器下载模块并加载,由于渲染是顺序进行的,当script标签阻塞时浏览器不会继续向下渲染DOM,因此页面会失去响应。因此,浏览器端只能采用异步方式加载模块。

2.AMD

AMD模块规范中,模块的加载是异步的,专用于浏览器端;使用时需要依赖第三方库RequireJs.

2.1 引入主模块

在html中通过<script>标签引入require.js库文件时,通过data-main属性指定主模块的路径:

<!--在html中-->
<script data-main="./index.js" src="./js/require.js"></script>

当require.js加载并执行后,会根据data-main属性指定的URL加载并运行主模块(此时为index.js).

2.2 定义模块

AMD使用define定义模块的信息、模块的依赖、函数。
第一个参数为模块的名称(不常使用,一般用后面两个参数),第二个参数为数组类型,依赖的模块,第三个参数为函数(用于返回定义的模块信息)。

// 定义没有依赖的模块
define(functioin(){return 模块对象
})// 定义有依赖的模块
define(['module1','module2'], function(m1, m2){// m1对应导入的module1对象, m2对应导入的module2对象return 模块对象
})

2.3 引入模块

// 主模块中用过requirejs.config指定模块的路径
requirejs.config({baseUrl: 'js/',paths: {module1: './modules/module1',module2: './modules/module2'}
})requirejs(['module1'], function (m1) {// 操作m1模块对象
})

通过requirejs函数引入模块,第一个参数为依赖的模块组数,第二个参数为回调函数。
另外,在主模块中通过requirejs.config指定模块的路径,baseUrl指定一个路径,后续配置路径时以此为相对路径(可选属性;paths中配置各个模块与模块文件路径的映射关系。

2.4 案例

案例使用的文件路径为:

-lib-require.js #依赖库
-js-module1.js-module2.js
-index.html
-index.js

index.js文件

(function (){requirejs.config({paths: {baseUrl: './js/',module1: './module1',module2: './module2'}})requirejs(['module1'], function (m1) {m1.print1("hello world")})})()

module1.js文件

define(['module2'], function (m2) {function print1 (param) {m2.print2(" -m1- "+param);}return { print1 }
})

module2.js文件

define(function () {function print2 (param) { console.log(" -m2- "+param)}return { print2 }
})

index.html文件

<!DOCTYPE html>  
<html>  
<head>  <script src="./lib/require.js" data-main="./index.js"></script>  
</head>  
<body>  
</body>  
</html>

浏览器console运行结果如下:

-m2-  -m1- hello world

注意:本地测试——直接通过浏览器访问html文件时,Chrome浏览器会因为跨域报错,可以进行如下参数设置:

--allow-file-access-from-files  --user-data-dir="空文件夹" --disable-web-security

3.CMD

CMD与AMD类似使用异步加载模块的机制,作为浏览器端的模块规范,区别在于CMD依赖提前下载,而CMD延迟下载,CMD的实现依赖于SeaJS。

3.1 引入主模块

<script src="./lib/sea.js"></script>
<script> seajs.use('./index.js')</script>

3.2 定义和加载模块

使用define定义模块,如下所示:

define(function(require, exports, module) {//...
})

其中:[1] require函数用于加载其他模块; [2] exports对象用于向外提供接口,导出对象或者方法;[3]存储当前模块的属性和方法。
require用法同AMD:

define(function(require, exports, module) {const m1 = require("./module1");m1.print1("hello world");
})

SeaJs也有use功能(在3.1章节中使用到),在需要先引入锁依赖的模块:

seajs.use(['module1', 'module2'], function(m1, m2){//...
});

3.3 案例

案例使用的文件路径为:

-lib-sea.js #依赖库
-js-module1.js-module2.js
-index.html
-index.js

index.js文件

define(function(require, exports, module) {const m1 = require("./js/module1");m1.print1("hello world");
})

module1.js文件

define(function(require, exports, module) {const m2 = require("./module2");exports.print1 = function(param) {m2.print2(" -m1- "+param)}
})

module2.js文件

define(function(require, exports, module) {exports.print2 = function(param) {console.log(" -m2- "+param)}
})

index.html文件

<!DOCTYPE html>  
<html>  
<head>  <script src="./lib/sea.js"></script><script> seajs.use('./index.js')</script>
</head>  
<body>  
</body>  
</html>

浏览器console运行结果如下:

 -m2-  -m1- hello world

4.ES6

ES6使用export和import关键词进行模块的导入和导出。

4.1 export和import

可以使用export指定本模块需要导出的对象(变量、方法、类等信息);在其他模块中通过import导入。
export:
export有两种使用方式,推荐 export { }形式。

// module1.js
export var test1 = "1";
export var fun1 = function() {console.log("hello world")
}

等价于:

// module1.js
var test1 = "1";
var fun1 = function(){console.log("hello world");
}export {test1,fun1
}

另外,导出时也可以执行别名, 如下所示:

// ...
export {test1,fun1 as fun1,fun1 as fun2
}

import:
使用import {...} from 模块 形式或使用import * as 别名 from 模块形式导入模块。

// index.js
import {test1, fun1} from "./module1";console.log(test1); //1
fun1(); // hello world

或者:

// index.js
import * as m1 from "./module1";console.log(m1.test1); //1
m1.fun1(); // hello world

导入时也可以指定别名:

import {test1, fun1 ad fun} from "./module1";

注意:使用 import{}和import * 不包括export default导出的对象。

4.2 export default和import

一个模块可以使用export default导出一个对象(变量、函数、类),import导入deault时不需要使用大括号。
在module1.js中使用export default导出一个默认输出:

// module1.js
export default function test1(){console.log("hello world")
}

在index.js中使用import导入:

// index.js
import test from "module1";
test();

导入默认导出项时,需要指定别名,此时为test.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/2736.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

揭秘油烟净化器保持餐饮厨房清新通畅的秘诀

我最近分析了餐饮市场的油烟净化器等产品报告&#xff0c;解决了餐饮业厨房油腻的难题&#xff0c;更加方便了在餐饮业和商业场所有需求的小伙伴们。 在餐饮厨房中&#xff0c;油烟净化器的作用不可忽视。它不仅是清洁空气的工具&#xff0c;更是提升生活品质的保障。让我们一…

音频数据分析注意事项

注意事项一、音频读取 1.librosa.load(path, sr16000) 读取的结果是&#xff0c;数据类型是浮点型 2.df_yin wave.open(path, rb) params df_yin.getparams() nchannels, sampwidth, framerate, nframes params[:4] strData df_yin.readframes(nframes) data np.frombuf…

笔记 | 嵌入式系统概论

1 嵌入式系统简介 1.1 嵌入式系统的定义 根据美国电气与电子工程师学会&#xff08;IEEE&#xff1a;Institute of Electrical and Electronics Engineers )的定义&#xff0c;嵌入式系统是用于控制、监视或辅助操作机器和设备的装置(原文: devices used to control, monitor…

WiFi、Ethenet、4G优先级切换

1、多网卡情况下如何调整优先级方案 按照目前公司前辈给出的方案&#xff0c;调整优先级的手段有两种&#xff1a; <1>.删除默认路由--route del 的方法 <2>.ifmetric源码提供的修改路由表的mteric的值来设置路由的优先级&#xff0c;metric越小优先级越高。 应…

ANSYS Help 的使用

ANSYS 帮助文档是相当实用且重要的第一手资料&#xff0c;90% 以上的纯操作问题都可以在帮助文档找到相关的解释。 点击开始菜单的 ANSYS Help即可打开帮助文档 帮助文档有两种打开方式&#xff1a; 基于帮助文档的安装包安装于本地后&#xff0c;可直接启动帮助程序没有安装…

Spring-IOC之组件扫描

版本 Spring Framework 6.0.9​ 1. 前言 通过自动扫描&#xff0c;Spring 会自动从扫描指定的包及其子包下的所有类&#xff0c;并根据类上的特定注解将该类装配到容器中&#xff0c;而无需在 XML 配置文件或 Java 配置类中逐一声明每一个 Bean。 支持的注解 Spring 支持一系…

书生·浦语大模型实战营之Llama 3 高效部署实践(LMDeploy 版)

书生浦语大模型实战营之Llama 3 高效部署实践&#xff08;LMDeploy 版&#xff09; 环境&#xff0c;模型准备LMDeploy chatTurmind和Transformer的速度对比LMDeploy模型量化(lite)LMDeploy服务(serve) 环境&#xff0c;模型准备 InternStudio 可以直接使用 studio-conda -t …

机器学习运用-民宿价格

项目简介 随着旅游业的蓬勃发展&#xff0c;民宿市场迎来了前所未有的增长机遇。正好最近在参加拓尔思数据挖掘公益实习活动&#xff0c;我的项目将应用机器学习技术开发一个价格预测模型。可以达到更好地理解和预测民宿价格的目的&#xff0c;该模型综合考虑了从容纳人数、便…

【Python】Python函数的黑魔法:递归,嵌套函数与装饰器

欢迎来到CILMY23的博客 本篇主题为&#xff1a; Python函数的黑魔法&#xff1a;递归&#xff0c;嵌套函数与装饰器 个人主页&#xff1a;CILMY23-CSDN博客 系列专栏&#xff1a;Python | C | C语言 | 数据结构与算法 感谢观看&#xff0c;支持的可以给个一键三连&#xff…

基于51单片机的矩阵按键扫描的proteus仿真

文章目录 一、按键按键按键消抖 二、独立按键仿真图仿真程序 三、矩阵按键仿真图仿真程序 四、总结 一、按键 按键 按键通常指的是电子设备上的一种输入装置&#xff0c;用于在按下时发送信号&#xff0c;以便设备执行相应的操作。按键可以分为独立按键和矩阵按键两种类型。 …

TRIZ理论下攀爬机器人的创新设计与研究

随着科技的飞速发展&#xff0c;机器人技术已广泛应用于各个领域。特别是在复杂环境下的作业&#xff0c;如灾难救援、太空探测等&#xff0c;对机器人的移动能力和适应性提出了更高要求。在这样的背景下&#xff0c;基于TRIZ理论的攀爬机器人设计与研究应运而生&#xff0c;它…

代码随想录三刷day46

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、力扣035. 不相交的线二、力扣53. 最大子数组和三、力扣392. 判断子序列 前言 每次当初始化的时候&#xff0c;都要回顾一下dp[i][j]的定义&#xff0c;不要…

简单的图像处理算法

本笔记参考crazy_Bingo 基础&#xff1a; 图像处理都是用卷积矩阵对图像卷积计算&#xff0c;如3X3 的矩阵对640 X 480分辨率的图像卷积&#xff0c;最终会得到638 X 478 的图像。卷积过程是这样的&#xff1a; 一、中值滤波 &#xff1a; 找出矩阵中的最中间值作为像素点 中…

Flink的安装、项目创建、任务打包和部署完整实现,任务实现使用JAVA语言

Flink资源下载地址 Flink安装包下载地址 一、本地模式安装Flink 1、在Linux服务上&#xff0c;创建flink文件夹 mkdir flink 2、上传文件并解压 tar -zxvf flink-1.14.6-bin-scala_2.11.tgz 解压完成后&#xff0c;如图&#xff1a; 3、启动Flink 进入到解压目录下&#x…

樱花下落的速度(区间放缩,思维)

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 已知一朵樱花有 n 枚花瓣&#xff0c;每一枚花瓣各不相同。将它们用一个长为 n 的排列编号。 我们根据一朵樱花的编号来认定它的特征&#xff1a; 每一个排列均具有两组特征码 fa&#xff0c;f…

YOLOv9训练损失、精度、mAP绘图功能 | 支持多结果对比,多结果绘在一个图片(消融实验、科研必备)

一、本文介绍 本文给大家带来的是YOLOv9系列的绘图功能&#xff0c;我将向大家介绍YOLO系列的绘图功能。我们在进行实验时&#xff0c;经常需要比较多个结果&#xff0c;针对这一问题&#xff0c;我写了点代码来解决这个问题&#xff0c;它可以根据训练结果绘制损失(loss)和mA…

使用官方代码打印yolov8 PyTorch模型结构

理解模型结构的重要性 在进行深度学习模型的开发时&#xff0c;一个清晰的模型结构有助于理解网络是如何从输入数据中提取特征&#xff0c;并执行分类或回归任务的。对于如YOLOv8这样的复杂模型来说&#xff0c;理解每个层的作用和相互间的连结尤为重要。 下面是我整合的代码…

ORACLE创建表空间及用户

创建用户之前需要先为用户创建表空间。 创建临时表空间&#xff1a;Oracle 临时表空间用于存储数据库操作过程中的临时数据&#xff0c;例如排序、哈希操作或者大查询的中间结果。临时表空间主要用于保证用户会话中的操作不会影响到系统的稳定性。 #用管理员登入数据库。 sq…

React的Key和diff

React的Key 先说说React组件的中Key,在渲染一个列表的时候,都要求设置一个唯一的Key,不然就会提示:Each child in a list should have a unique "key" prop. 意思是列表的每一个子元素都应该需要设置一个唯一的key值。在开发中一搬会以id作为key。比如 const …

Java的八大基本数据类型和 println 的介绍

前言 如果你有C语言的基础&#xff0c;这部分内容就会很简单&#xff0c;但是会有所不同~~ 这是我将要提到的八大基本数据类型&#xff1a; 注意&#xff0c;Java的数据类型是有符号的&#xff01;&#xff01;&#xff01;和C语言不同&#xff0c;Java不存在无符号的数据。 整…