if (util.isFunction(factory)) {
186 compileStack.push(module)
187 runInModuleContext(factory, module)
188 compileStack.pop()
189 }
这里就是把module.export进行初始化。runInModuleContext方法:
复制代码 代码如下:
// 根据模块上下文执行模块代码
489 function runInModuleContext(fn, module) {
490 // 传入与模块相关的两个参数以及模块自身
491 // exports用来暴露接口
492 // require用来获取依赖模块(同步)(编译)
493 var ret = fn(module.require, module.exports, module)
494 // 支持返回值暴露接口形式,如:
495 // return {
496 // fn1 : xx
497 // ,fn2 : xx
498 // ...
499 // }
500 if (ret !== undefined) {
501 module.exports = ret
502 }
503 }
执行a.js中的function方法,这时会调用var b = require("b.js"),
require方法会返回b的compile方法的返回值,b模块中又有var c = require('c.js')。
这时会调用c的compile方法,然后调用c的function,c中,如果要暴露对象,或者是return 对象c,则模块c的exports = c。或者直接是module.export = c;总之最后会返回module c.export = c;所以var c = module c.export = c,模块b中,就可以使用变量c调用模块c中的c对象的方法和属性。
以此类推,最终a模块也能调用b模块中b对象的属性和方法。
不管什么模块,只要使用了module.export = xx模块,其他模块就可以使用require("xx模块"),调用xx模块中的各种方法了。
最终模块的状态会变成module.status = STATUS.COMPILED。
复制代码 代码如下:
Module.prototype._use = function(ids, callback) {
var uris = resolve(ids, this.uri); //解析['./a','jquery']
this._load(uris, function() { //把解析出来的a,jquery模块的地址[url1,url2],调用_load方法。
//util.map : 让数据成员全部执行一次一个指定的函数,并返回一个新的数组,该数组为原数组成员执行回调后的结果
var args = util.map(uris, function(uri) {
return uri ? cachedModules[uri]._compile() : null;//如果存在url,就调用_compile方法。
})
if (callback) { callback.apply(null, args) }
})
}
这时args = [module a.export, module jquery.export];
复制代码 代码如下:
seajs.use(['./a','jquery'],function(a,$){
var num = a.a;
$('#J_A').text(num);
})
这时function中的a和$就是module a.export和module jquery.export。
因为本人现在在研究jquery源码和jquery框架设计,因此共享一些经验:
jquery源码,我在网上看了很多解析,看着看着就看不下去了。意义不大,推荐妙味课堂的jquery源码解析。
司徒正美的javascript框架设计,个人觉得难度大,但是精读后,你就是高级前端工程师了。
玉伯的sea.js,我建议去学习,去用,毕竟是中国人自己做的。我们公司新的项目或者重构,都会使用seajs来做。