javascript中的模块系统_javascript 模块
itomcoil 2025-08-21 03:13 3 浏览
简介
在很久以前,js只是简单的作为浏览器的交互操作而存在,一般都是非常短小的脚本,所以都是独立存在的。
但是随着现代浏览器的发展,特别是nodejs的出现,js可以做的事情变得越来越多也越来越复杂。于是我们就需要模块系统来组织不同用途的脚本,进行逻辑的区分和引用。
今天将会给大家介绍一下js中的模块系统。
CommonJS和Nodejs
CommonJS是由Mozilla公司在2009年1月份提出来了。没错,就是那个firfox的公司。
最初的名字叫做ServerJS,在2009年8月的时候为了表示这个标准的通用性,改名为CommonJS。
CommonJS最主要的应用就是服务端的nodejs了。浏览器端是不直接支持CommonJS的,如果要在浏览器端使用,则需要进行转换。
CommonJS使用require()来引入模块,使用module.exports来导出模块。
我们看一个CommonJS的例子:
require("module");
require("../file.js");
exports.doStuff = function() {};
module.exports = someValue;
注意,CommonJS是同步加载的。
AMD异步模块加载
AMD的全称是Asynchronous Module Definition 。它提供了一个异步加载模块的模式。
AMD是RequireJS在推广过程中对模块定义的规范化产出。
异步加载的好处就是可以在需要使用模块的时候再进行加载,从而减少了一次性全部加载的时间,尤其是在浏览器端,可以提升用户的体验。
看下AMD加载模块的定义:
define(id?, dependencies?, factory);
AMD是通过define来定义和加载依赖模块的。
其中id表示要定义的模块的名字,dependencies表示这个模块的依赖模块,factory是一个函数,用来初始化模块或者对象。
我们看一个例子:
define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
exports.verb = function() {
return beta.verb();
//Or:
return require("beta").verb();
}
});
这个例子中,我们定义了一个alpha模块,这个模块需要依赖”require”, “exports”, “beta”三个模块。
并且在factory中导出了beta模块的verb方法。
define中id和dependencies都不是必须的:
//无id
define(["alpha"], function (alpha) {
return {
verb: function(){
return alpha.verb() + 2;
}
};
});
//无依赖
define({
add: function(x, y){
return x + y;
}
});
甚至我们可以在AMD中使用CommonJS:
define(function (require, exports, module) {
var a = require('a'),
b = require('b');
exports.action = function () {};
});
定义完之后,AMD使用require来加载模块:
require([dependencies], function(){});
第一个参数是依赖模块,第二个参数是回调函数,会在前面的依赖模块都加载完毕之后进行调用。加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块。
require(["module", "../file"], function(module, file) { /* ... */ });
require加载模块是异步加载的,但是后面的回调函数只会在所有的模块都加载完毕之后才运行。
CMD
CMD是SeaJS在推广过程中对模块定义的规范化产出。它的全称是Common Module Definition。
CMD也是使用define来定义模块的,CMD推崇一个文件作为一个模块:
define(id?, deps?, factory)
看起来和AMD的define很类似,都有id,依赖模块和factory。
这里的factory是一个函数,带有三个参数,function(require, exports, module)
我们可以在factory中通过require来加载需要使用的模块,通过exports来导出对外暴露的模块,module表示的是当前模块。
我们看一个例子:
// 定义模块 myModule.js
define(function(require, exports, module) {
var = require('jquery.js')('div').addClass('active');
});
// 加载模块
seajs.use(['myModule.js'], function(my){
});
所以总结下AMD和CMD的区别就是,AMD前置要加载的依赖模块,在定义模块的时候就要声明其依赖的模块。
而CMD加载完某个依赖模块后并不执行,只是下载而已,只有在用到的时候才使用require进行执行。
ES modules和现代浏览器
ES6和现代浏览器对模块化的支持是通过import和export来实现的。
首先看下import和export在浏览器中支持的情况:
首先我们看下怎么使用export导出要暴露的变量或者方法:
export const name = 'square';
export function draw(ctx, length, x, y, color) {
ctx.fillStyle = color;
ctx.fillRect(x, y, length, length);
return {
length: length,
x: x,
y: y,
color: color
};
}
基本上,我们可以使用export导出var, let, const变量或者function甚至class。前提是这些变量或者函数处于top-level。
更简单的办法就是将所有要export的放在一行表示:
export { name, draw, reportArea, reportPerimeter };
export实际上有两种方式,named和default。上面的例子中的export是named格式,因为都有自己的名字。
下面看下怎么使用export导出默认的值:
// export feature declared earlier as default
export { myFunction as default };
// export individual features as default
export default function () { ... }
export default class { .. }
named可以导出多个对象,而default只可以导出一个对象。
导出之后,我们就可以使用import来导入了:
import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
如果导出的时候选择的是default,那么我们在import的时候可以使用任何名字:
// file test.js
let k; export default k = 12;
// some other file
import m from './test'; // 因为导出的是default,所以这里我们可以使用import m来引入
console.log(m); // will log 12
我们可以在一个module中使用import和export从不同的模块中导入,然后在同一个模块中导出,这样第三方程序只需要导入这一个模块即可。
export { default as function1,
function2 } from 'bar.js';
上面的export from 等价于:
import { default as function1,
function2 } from 'bar.js';
export { function1, function2 };
上面的例子中,我们需要分别import function1 function2才能够使用,实际上,我们可以使用下面的方式将所有的import作为Module对象的属性:
import * as Module from './modules/module.js';
Module.function1()
Module.function2()
然后function1,function2就变成了Module的属性,直接使用即可。
在HTML中使用module和要注意的问题
怎么在HTML中引入module呢?我们有两种方式,第一种是使用src选项:
<script type="module" src="main.js"></script>
第二种直接把module的内容放到script标签中。
<script type="module">
/* JavaScript module code here */
</script>
注意,两种script标签的类型都是module。
在使用script来加载module的时候,默认就是defer的,所以不需要显示加上defer属性。
如果你在测试的时候使用file:// 来加载本地文件的话,因为JS模块安全性的要求,很有可能得到一个CORS错误。
最后,import() 还可以作为函数使用,来动态加载模块:
squareBtn.addEventListener('click', () => {
import('./modules/square.js').then((Module) => {
let square1 = new Module.Square(myCanvas.ctx, myCanvas.listId, 50, 50, 100, 'blue');
square1.draw();
square1.reportArea();
square1.reportPerimeter();
})
});
本文作者:flydean程序那些事
本文链接:
http://www.flydean.com/js-modules/本文来源:flydean的博客
欢迎关注我的公众号:「程序那些事」最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
相关推荐
- 最强聚类模型,层次聚类 !!_层次聚类的优缺点
-
哈喽,我是小白~咱们今天聊聊层次聚类,这种聚类方法在后面的使用,也是非常频繁的~首先,聚类很好理解,聚类(Clustering)就是把一堆“东西”自动分组。这些“东西”可以是人、...
- python决策树用于分类和回归问题实际应用案例
-
决策树(DecisionTrees)通过树状结构进行决策,在每个节点上根据特征进行分支。用于分类和回归问题。实际应用案例:预测一个顾客是否会流失。决策树是一种基于树状结构的机器学习算法,用于解决分类...
- Python教程(四十五):推荐系统-个性化推荐算法
-
今日目标o理解推荐系统的基本概念和类型o掌握协同过滤算法(用户和物品)o学会基于内容的推荐方法o了解矩阵分解和深度学习推荐o掌握推荐系统评估和优化技术推荐系统概述推荐系统是信息过滤系统,用于...
- 简单学Python——NumPy库7——排序和去重
-
NumPy数组排序主要用sort方法,sort方法只能将数值按升充排列(可以用[::-1]的切片方式实现降序排序),并且不改变原数组。例如:importnumpyasnpa=np.array(...
- PyTorch实战:TorchVision目标检测模型微调完
-
PyTorch实战:TorchVision目标检测模型微调完整教程一、什么是微调(Finetuning)?微调(Finetuning)是指在已经预训练好的模型基础上,使用自己的数据对模型进行进一步训练...
- C4.5算法解释_简述c4.5算法的基本思想
-
C4.5算法是ID3算法的改进版,它在特征选择上采用了信息增益比来解决ID3算法对取值较多的特征有偏好的问题。C4.5算法也是一种用于决策树构建的算法,它同样基于信息熵的概念。C4.5算法的步骤如下:...
- Python中的数据聚类及可视化分析实践
-
探索如何通过聚类分析揭露糖尿病预测数据集的特征!我们将运用Python的强力工具,深入挖掘数据,以直观的可视化揭示不同特征间的关系。一同探索聚类分析在糖尿病预测中的实践!所有这些可视化都可以通过数据操...
- 用Python来统计大乐透号码的概率分布
-
用Python来统计大乐透号码的概率分布,可以按照以下步骤进行:导入所需的库:使用Python中的numpy库生成数字序列,使用matplotlib库生成概率分布图。读取大乐透历史数据:从网络上找到大...
- python:支持向量机监督学习算法用于二分类和多分类问题示例
-
监督学习-支持向量机(SVM)支持向量机(SupportVectorMachine,简称SVM)是一种常用的监督学习算法,用于解决分类和回归问题。SVM的目标是找到一个最优的超平面,将不同类别的...
- 25个例子学会Pandas Groupby 操作
-
groupby是Pandas在数据分析中最常用的函数之一。它用于根据给定列中的不同值对数据点(即行)进行分组,分组后的数据可以计算生成组的聚合值。如果我们有一个包含汽车品牌和价格信息的数据集,那么可以...
- 数据挖掘流程_数据挖掘流程主要有哪些步骤
-
数据挖掘流程1.了解需求,确认目标说一下几点思考方法:做什么?目的是什么?目标是什么?为什么要做?有什么价值和意义?如何去做?完整解决方案是什么?2.获取数据pandas读取数据pd.read.c...
- 使用Python寻找图像最常见的颜色_python 以图找图
-
如果我们知道图像或对象最常见的是哪种颜色,那么可以解决图像处理中的几个用例,例如在农业领域,我们可能需要确定水果的成熟度。我们可以简单地检查一下水果的颜色是否在预定的范围内,看看它是成熟的,腐烂的,还...
- 财务预算分析全网最佳实践:从每月分析到每天分析
-
原文链接如下:「链接」掌握本文的方法,你就掌握了企业预算精细化分析的能力,全网首发。数据模拟稍微有点问题,不要在意数据细节,先看下最终效果。在编制财务预算或业务预算的过程中,通常预算的所有数据都是按月...
- 常用数据工具去重方法_数据去重公式
-
在数据处理中,去除重复数据是确保数据质量和分析准确性的关键步骤。特别是在处理多列数据时,保留唯一值组合能够有效清理数据集,避免冗余信息对分析结果的干扰。不同的工具和编程语言提供了多种方法来实现多列去重...
- Python教程(四十):PyTorch深度学习-动态计算图
-
今日目标o理解PyTorch的基本概念和动态计算图o掌握PyTorch张量操作和自动求导o学会构建神经网络模型o了解PyTorch的高级特性o掌握模型训练和部署PyTorch概述PyTorc...
- 一周热门
- 最近发表
- 标签列表
-
- ps图案在哪里 (33)
- super().__init__ (33)
- python 获取日期 (34)
- 0xa (36)
- super().__init__()详解 (33)
- python安装包在哪里找 (33)
- linux查看python版本信息 (35)
- python怎么改成中文 (35)
- php文件怎么在浏览器运行 (33)
- eval在python中的意思 (33)
- python安装opencv库 (35)
- python div (34)
- sticky css (33)
- python中random.randint()函数 (34)
- python去掉字符串中的指定字符 (33)
- python入门经典100题 (34)
- anaconda安装路径 (34)
- yield和return的区别 (33)
- 1到10的阶乘之和是多少 (35)
- python安装sklearn库 (33)
- dom和bom区别 (33)
- js 替换指定位置的字符 (33)
- python判断元素是否存在 (33)
- sorted key (33)
- shutil.copy() (33)