define('alpha' ,['require', "exports", "module"], function(require, exports, module) { var foo = require('foo'); module.exports = exports = function() { foo.doSomething(); } });
参数node
第一个是要定义的模块名字(id)
第二个是要用到的模块名,其实更专业点讲是定义的这个模块所依赖的模块名称
第三个回调函数,是要定义模块内容app
分析方法:替换部分代码进行分析模块化
先来把回调中的require,exports,module替换了看看。函数
function callback(exports, module) { // 假设foo是最简单的对象,把require('foo')换成最简答的对象看看 var foo = { 'doSomething': function() {} }; module.exports = exports = function() { foo.doSomething(); } }
那么其实已经不难看出,require其实就至关因而个查询函数吧,我给他传个对象名,它就能给我一个具体的对象。优化
var require = function(name) { var modules = {'foo': {'doSomething': function() {}}}; return modules[name] || {}; }
那么整个代码能够换成ui
var require = function(name) { var modules = {'foo': {'doSomething': function() {}}}; return modules[name] || {}; } function callback(exports, module) { var foo = require('foo'); module.exports = exports = function() { foo.doSomething(); } }
看起来好像有点道理哦,等会儿,等会儿,这里的modules又从哪儿冒出来的,哈哈哈,被发现了,别急慢慢来code
在替换以前,先来了解下exports和module.exports这两货是干啥的,而要了解他们先来看看模块是啥。对象
其实模块么,简单来讲就是一个高级别的function,输入,处理,输出。至于为啥js的模块化为啥这么困难,这个问题不是三言两语就能解释清楚的,就不展开了(其实真实状况是,我也不清楚,哈哈哈)内存
既然模块要作输出,那么输出什么东西总要知道吧,而module.exports的做用就是这个,存储模块输出的内容。get
也就是说,这个模块中要给外部使用的东西全放在module.exports里头了。废话真多,是的哈- -.
而要说清exports和module.exports的二三事,又不是件容易的事,简单理解,exports和module.exports指向同一内存区域。有兴趣能够看看exports 和 module.exports 的区别。
那来改造一下,把module.exports,exports也提炼出来看看
var require = function(name) { var modules = {'foo': {'doSomething': function() {}}}; return modules[name] || {}; } var module = {}; var module.exports = exports = {}; function callback() { var foo = require('foo'); module.exports = exports = function() { foo.doSomething(); } }
// 这里的id至关于模块名,deps就是须要依赖的模块名称列表 define = function(id , deps, callback) { callback(require, exports, module); };
晕,那require,exports,module跑哪儿溜达去了?加上去看看
define = function(id , deps, callback) { var require = function(name) { var modules = {'foo': {'doSomething': function() {}}}; return modules[name] || {}; } var module = {}; var module.exports = exports = {}; callback(require, exports, module); };
看上去挺有道理的么,那么modules这玩意儿究竟是哪儿冒出来的呢。
能够看出来modules 里面存放着的是foo模块的内容,那这些内容是怎么来的呢?经过foo的module.exports提供的啊。那么modules里面其实放的是,foo的module.exports。
而foo对于当前模块来讲是外部的模块。而我想调用外面的东西,只有两种办法,要么传参数,要么经过全局变量(不过或许大神还有其余方案,我就只晓得这两种了)。define里面有的参数没有一个是存放module.exports的。那么答案呼之欲出了,modules是全局变量。
modules = {}; function load(id, exports) { (modules || (modules = {}))[id] = exports; }
再来看看完整的代码,变成啥样了
modules = {}; function load(name, exports) { (modules || (modules = {}))[name] = exports; } define = function(id, deps, callback) { var require = function(name) { return modules[name] || {}; } var module = {}; var module.exports = exports = {}; callback(require, exports, module); load(id, module.exports); };
到如今差很少已经成型了,那么这里的require, exports, module都是外来的模块吧bingo,其实callback里的模块都是根据deps来的,去掉require, exports, module
modules = {}; function load(name, exports) { (modules || (modules = {}))[name] = exports; } define = function(id, deps, callback) { // 至关于 // var module = {}; // var module.exports = {}; var module = modules['module']; // 至关于 //var require = function(name) { // return modules[name] || {}; //} var require = modules['require']; var args = deps.map(require); callback.apply(null, args); load(id, module.exports); };
define('alpha' ,['foo'], function(foo) { return function() { foo.doSomething(); } });
咦,精简了很多诶。没有exports了诶,会返回了么
modules = {}; function load(name, exports) { (modules || (modules = {}))[name] = exports; } define = function(id, deps, callback) { var module = modules['module']; var require = modules['require']; var args = deps.map(require); var exports = callback.apply(null, args); load(id, exports || module.exports); };
OK,先告一段落了,累死我丫了。在慢慢优化吧,唉。
exports 和 module.exports 的区别这篇文章很不赖。
人家大神已经说得很是好了。我在了浅薄的打个比方,我有个文件夹叫module.exports,而后我建立了一个超连接叫exports,那我在任何一个里面操做最终都会反应到另外一个里,但若是我把超连接exports删了把它的指向地址改了,并不会影响真正的文件夹module.exports。
而有不少人明明已经改了超连接exports的指向地址(如:exports = 123;),再在超连接里面作了不少操做(如:exports.hello = 456;),那都不会对真正的文件夹module.exports起到任何做用(你是见不到module.exports.hello === 456的)。