0

0

用js实现简易模块加载器的方法

一个新手

一个新手

发布时间:2017-10-11 10:07:23

|

1848人浏览过

|

来源于php中文网

原创


前言

前一段时间分析过require.js源码,整体的分析有些泛泛而,谈内容有些空洞,没有把握住requirejs依赖处理的精髓, 这是分析require.js源码最为失败的地方。

虽然没有真正的理解其实现细节,但是对其源码组织以及基本的逻辑执行有了整体的了解。

本文是参考网上的源码,分析其思想实现的简易的模块加载器,旨在加深对于require.js的认知与理解。

实现思路

首先明确的几点如下:

  • 每调用一次require函数,就会创建一个Context对象

  • Module对象表示模块对象,基本的操作都是该对象的原型方法

上面两个对象是实现该简易模块加载器核心,加载过程中的处理流程如下图所示:
加载流程
加载流程代码

Module对象的属性有:

mid:表示模块id  src:模块路径  name: 模块名称  deps:模块的依赖列表  callback:回调函数  errback:错误处理函数  status:模块状态  exports:与回调函数参数序列对应的模块输出

Module的原型对象有如下几个方法:

init:Module对象的初始化处理
 fetch:创建script节点并追加到元素节点上
 checkCycle:处理循环依赖,返回当前的循环依赖列表
 handleDeps:处理依赖列表
 changeStatus:改变模块的状态,主要处理模块是否加载成功
 execute:依赖的模块都加载成功后,参数列表的获取

如何处理依赖列表的

事实上,处理依赖列表是define以及require中处理,define函数以及require函数的处理代码如下:
define及require

首先看require函数,实例:

require(['a', 'b'], function(a, b) {
    console.log(a, b);
});

从上面可以看出,调用require函数,依赖列表是[‘a’, ‘b’],回调函数是function(a, b) {console.log(a, b);}

95Shop仿醉品商城
95Shop仿醉品商城

95Shop可以免费下载使用,是一款仿醉品商城网店系统,内置SEO优化,具有模块丰富、管理简洁直观,操作易用等特点,系统功能完整,运行速度较快,采用ASP.NET(C#)技术开发,配合SQL Serve2000数据库存储数据,运行环境为微软ASP.NET 2.0。95Shop官方网站定期开发新功能和维护升级。可以放心使用! 安装运行方法 1、下载软件压缩包; 2、将下载的软件压缩包解压缩,得到we

下载

从require代码可以就看出,调用Context构造函数创建一个Context对象,现在看下Context构造函数的处理:let Context = function(deps, callback, errback) {

    this.cid = ++contextId;
    this.init(deps, callback, errback);
}
;
    Context.prototype.init = function(deps, callback, errback) {
    this.deps = deps;
    this.callback = callback;
    this.errback = errback;
    contexts[this.cid] = this;
}
;

上面中重要的是contexts[this.cid] = this;将当前的Context对象注册到全局contexts对象集合中。

然后调用handleDeps函数,该函数处理依赖列表,具体的代码如下:handleDeps: function() {

    let depCount = this.deps ? this.deps.length : 0;
    // require.js中处理循环依赖的处理 let requireInDep = (this.deps || []).indexOf('require');
    if (requireInDep !== -1) {
    depCount--;
    this.requireInDep = requireInDep;
    this.deps.splice(requireInDep, 1);
}
// 处理循环依赖情况 let cycleArray = this.checkCycle();
    if (cycleArray) {
    depCount = depCount - cycleArray.length;
}
// depCount表示当前模块的依赖模块数,depCount为0表示模块中某一依赖加载完成 this.depCount = depCount;
    if (depCount === 0) {
    this.execute();
    return;
}
// 遍历依赖列表,创建Module对象,并且将当前模块与其依赖的关系构建出来maps this.deps.forEach((depModuleName) => {
    if (!modules[depModuleName]) {
    let module = new Module(depModuleName);
    modules[module.name] = module;
}
if (!maps[depModuleName]) {
    maps[depModuleName] = [];
}
maps[depModuleName].push(this);
}
);

}循环依赖的处理

本次实现代码中的循环依赖的处理,是require.js中官方的方法,就是传递require在回调函数中再次require,为什么这样就可以解决循环依赖?

就本次实现而言,因为require一次就会创建一个Context对象。主要代码如下:// require.js中处理循环依赖的处理let requireInDep = (this.deps || []).indexOf('require');
 

   if (requireInDep !== -1) {
    depCount--;
    this.requireInDep = requireInDep;
    this.deps.splice(requireInDep, 1);
}
// 获取循环依赖 let cycleArray = this.checkCycle();
    if (cycleArray) {
    depCount = depCount - cycleArray.length;
}
// execute函数中代码// 插入require到回调函数的参数列表中if (this.requireInDep !== -1 && this.requireInDep !== undefined) {
    arg.splice(this.requireInDep, 0, require);
}

结束语

纸上得来终觉浅,觉知此事要躬行,通过实现简易的模块加载器,对于require.js模块加载的思想以及逻辑处理更加地清晰。

虽然与require.js对于js文件的异步加载的处理方式不同,但是本质是一样的,require.js是添加script节点到head标签中,并且script添加async属性来实现异步加载的。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

8

2026.01.30

c++ 字符串格式化
c++ 字符串格式化

本专题整合了c++字符串格式化用法、输出技巧、实践等等内容,阅读专题下面的文章了解更多详细内容。

8

2026.01.30

java 字符串格式化
java 字符串格式化

本专题整合了java如何进行字符串格式化相关教程、使用解析、方法详解等等内容。阅读专题下面的文章了解更多详细教程。

6

2026.01.30

python 字符串格式化
python 字符串格式化

本专题整合了python字符串格式化教程、实践、方法、进阶等等相关内容,阅读专题下面的文章了解更多详细操作。

1

2026.01.30

java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

20

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

17

2026.01.29

java成品学习网站推荐大全
java成品学习网站推荐大全

本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

18

2026.01.29

Java字符串处理使用教程合集
Java字符串处理使用教程合集

本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

3

2026.01.29

Java空对象相关教程合集
Java空对象相关教程合集

本专题整合了Java空对象相关教程,阅读专题下面的文章了解更多详细内容。

6

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 4.3万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 2.5万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号