You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请教JavaScript打包器工作原理及一段require函数代码解析

拆解这段简化版require函数的工作逻辑

嘿,我来帮你拆解这段代码——它其实是打包器(比如Webpack、Browserify)实现模块加载核心逻辑的极简缩影,咱们一步步来理清楚:

首先得明确这段代码依赖的两个全局变量的作用:

  • modules:这是一个模块注册表,键是模块名称/ID,值是该模块的定义函数。这个函数会接收一个exports对象,模块里要对外暴露的内容都会挂载到这个对象上。
  • dependencies:这是一个模块缓存池,用来存储已经加载执行过的模块的导出结果,避免重复加载同一个模块。

接下来逐行解析函数逻辑:

  1. 函数入口

    var require = function (module) {
    

    这个require就是我们日常导入模块时用的函数,参数module是你要加载的模块的名称或唯一ID。

  2. 缓存检查

    if (!dependencies[module]) {
    

    先判断目标模块是否已经被加载过:如果dependencies里没有这个模块的记录,说明模块还未加载,进入加载流程;如果有记录,直接跳过加载步骤,返回缓存的结果。

  3. 创建导出容器

    var exports = {}
    

    新建一个空的exports对象,这个对象就是模块用来向外“公开”内容的容器——模块内部的代码会把要暴露的变量、方法挂载到这个对象上。

  4. 执行模块定义

    modules[module](exports)
    

    从modules注册表中取出对应模块的定义函数,把刚创建的exports对象传进去执行。比如模块里写了exports.add = (a,b) => a+b,执行后exports就会带上add方法。

  5. 缓存模块结果

    dependencies[module] = exports
    

    把已经填充好内容的exports存入dependencies缓存池,这样下次再调用require加载同一个模块时,直接复用缓存的结果,不会重复执行模块代码——这就是模块的单例特性,一个模块只会被加载执行一次。

  6. 返回导出内容

    return dependencies[module]
    

    不管模块是刚加载的还是来自缓存,最终返回该模块的导出结果,这样调用require的地方就能拿到模块暴露的内容了。

举个简单的例子帮你理解

假设我们有打包后的模块集合和缓存对象:

// 模拟打包后的模块注册表
var modules = {
  'utils/math': function(exports) {
    // 模块内部把要暴露的方法挂到exports上
    exports.add = function(a, b) {
      return a + b;
    };
  }
};
// 模块缓存池
var dependencies = {};

第一次调用require('utils/math')时:

  • 因为dependencies['utils/math']不存在,会创建空exports,执行modules['utils/math'](exports),让exports带上add方法;
  • 然后把这个exports存入缓存;
  • 最后返回这个exports,你就能用math.add(1,2)得到结果3。

第二次再调用require('utils/math')时,直接从dependencies里取出缓存的exports返回,不会再执行模块里的代码。

内容的提问来源于stack exchange,提问作者Wayne Zhao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:16:25