一个模块加载器一般来说会在全局暴露出 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)
以上代码为模块加载器的简易实现,未涉及模块的网络下载以及循环引用的处理。