站点工具

用户工具


手写简易模块加载器

需求

一个模块加载器一般来说会在全局暴露出 define 和 require 两个函数。

define用来定义一个模块,其参数为:当前的模块名、依赖的模块名列表、当前模块的实现。

require用来加载并执行模块,其参数为:运行依赖的模块名列表、当前要执行的函数。

为此,我们需要对 define和requrie进行实现,以实现如下调用。

function define(name, deps, callback) {
  // todo...
}
 
function require(deps, callback) {
  // todo...
}
 
 
define('firstName', [], () => {
  return '饥人谷'
})
 
define('lastName', [], () => {
  return '前端'
})
 
define('sayHello', ['firstName', 'lastName'], (v1, v2) => {
  return function() {
    console.log(`Hello ${v1} ${v2}`)
  }
})
 
require(['sayHello'], (fn) => {
  fn()
})

简易模块加载器雏形

let modules = {}
 
function define(name, deps, callback) {
  depFns = deps.map(depName => modules[depName])
  modules[name] = callback.apply(null, depFns)
}
 
function require(deps, callback) {
  depFns = deps.map(depName => modules[depName])
  callback.apply(null, depFns)
}

实现原理为:当定义一个模块时,先从依赖的模块名列表得到这些依赖的模块的函数实现构成的数组,给modules添加一个属性,其值为模块实现执行后的结果,其参数为依赖的模块实现函数数组。

优化

(global => {
  let modules = {}
 
  function require(deps, callback) {      
    if(!Array.isArray(deps)) {
      callback = deps
      deps = []
    }
    depFns = deps.map(depName => modules[depName])
    return callback.apply(null, depFns)
  }
 
  function define(name, deps, callback) {
    modules[name] = require(deps, callback)
  }
 
  global.define = define
  global.require = require
 
})(window)

以上代码为模块加载器的简易实现,未涉及模块的网络下载以及循环引用的处理。

饥人谷一直致力于培养有灵魂的编程者,打造专业有爱的国内前端技术圈子。如造梦师一般帮助近千名不甘寂寞的追梦人把编程梦变为现实,他们以饥人谷为起点,足迹遍布包括facebook、阿里巴巴、百度、网易、京东、今日头条、大众美团、饿了么、ofo在内的国内外大小企业。 了解培训课程:加微信 xiedaimala03,官网:https://jirengu.com

本文作者:饥人谷若愚老师,如未经饥人谷官方同意,禁止转载

若愚 · 2023/02/09 10:49 · 手写简易模块加载器_手写系列四.txt