3(phonegap源码分析)模块定义与请求(define require)
2013-08-09 19:11
411 查看
define和require是贯彻整个phonegap代码的核心函数,它们通过定义的一个匿名函数的即时调用来赋值的。事实上下面的匿名函数中省略了部分代码,当然省略的代码并不影响框架的主题功能,而是新版本中对原有功能的完善。
怎么来理解这部分代码呢?如果按其他面向对象语言(JAVA或C++)来理解,可以把这个匿名函数当做一个类,这个类对外提供两个外部方法,一个是require,一个是define,当然还有一个私有方法build,这个类的主要成员变量就是modules,好吧,modules,这个变量确实也没有其他地方直接使用它了。
modules是什么呢,modules字面意义是模型,那这个变量就是存储模块对象的。由前面得知,require和define的功能分别为请求和定义模块。但是并不是所有的模块在一开始就加载的,而模块也并不是每次请求都重新生成的。
所以modules就如同一个哈希表,主键就是模块名,比如”myphonegap”、”myphonegap/common”,值就是相应模块对象或模块对象的工厂函数。先通过define对这个哈希表添加一个主键模块名,和构建这个模块的工厂方法,此时是没有模块对象的;如果是第一次请求该模块,就会通过工厂函数来生成模块,生成模块之后对应的工厂方法会从表中删除,而如果已经请求过的模块就能在modules中找到对应模块对象。
现在来测试下,在myphonegap模块的工厂函数中添加一个打印输入语句,然后通过html加载这个js文件执行看结果。
下面是HTML文件的源码,js文件放置在html文件同级的js文件夹内。之后的例子也会通过这种方式来执行,除非要用到android的交互功能了。
运行结构如图,浏览器为chrome,下面显示的部分是它的“开发者工具”console下的内容
这里只执行了myphonegap模块工厂函数的代码,而myphonegap/builer的并没有执行,因为只有myphonegap模块被请求了。
myphonegap.js 源码
var require,//myphonegap内部的工具函数,用来导入相关的模块 define;//在myphonegap注册相关的模块 //通过一个立即调用的匿名函数,来给require和define赋上实际的函数 (function(){ var modules={}; // 模块数组,添加模块类似给这个对象添加了属性,模块名为属性名,模块对象为属性值,或者说是键值对 build = function(module){ //根据模块对象构造模块导出对象,模块导出对象存储在modules这个对象数组内 var factory = module.factory; module.exports = {}; //给当前模块加入了一个exports属性 delete module.factory; //删除了module的属性 factory(require,module.exports,module); //构建导出模块,module.exports是传出参数(实参,引用传递) return module.exports; } require = function(id){ //根据模块名称/id请求模块对象,如果是第一次请求,就构建对象 if(!modules[id]){ throw "module " + id + " not found!"; } return modules[id].factory?build(modules[id]):modules[id].exports; } define = function(id,factory){ //定义模块,模块名称、构建模块对象的工厂方法。 if(modules[id]){ throw "module " + id + " is exist!"; } modules[id] = { //定义模块对象,左边的值为属性名,右边的值为传入的参数 id:id, factory:factory }; } })();
怎么来理解这部分代码呢?如果按其他面向对象语言(JAVA或C++)来理解,可以把这个匿名函数当做一个类,这个类对外提供两个外部方法,一个是require,一个是define,当然还有一个私有方法build,这个类的主要成员变量就是modules,好吧,modules,这个变量确实也没有其他地方直接使用它了。
modules是什么呢,modules字面意义是模型,那这个变量就是存储模块对象的。由前面得知,require和define的功能分别为请求和定义模块。但是并不是所有的模块在一开始就加载的,而模块也并不是每次请求都重新生成的。
所以modules就如同一个哈希表,主键就是模块名,比如”myphonegap”、”myphonegap/common”,值就是相应模块对象或模块对象的工厂函数。先通过define对这个哈希表添加一个主键模块名,和构建这个模块的工厂方法,此时是没有模块对象的;如果是第一次请求该模块,就会通过工厂函数来生成模块,生成模块之后对应的工厂方法会从表中删除,而如果已经请求过的模块就能在modules中找到对应模块对象。
现在来测试下,在myphonegap模块的工厂函数中添加一个打印输入语句,然后通过html加载这个js文件执行看结果。
//注册myphonegap模块 define("myphonegap", function(require, exports, module){ console.info("create myphonegap module"); var myphonegap = { Hello:function(name){ console.info("hello, "+name +" !"); } }; module.exports = myphonegap; }); //注册myphonegap/builder模块 define("myphonegap/builder", function(require, exports, module){ console.info("create myphonegap/builder module"); });
下面是HTML文件的源码,js文件放置在html文件同级的js文件夹内。之后的例子也会通过这种方式来执行,除非要用到android的交互功能了。
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <script type="text/javascript" charset="utf-8" src="js/myphonegap.js"></script> </head> <body> <p>MYPHONEGAP !</p> </body> </html>
运行结构如图,浏览器为chrome,下面显示的部分是它的“开发者工具”console下的内容
这里只执行了myphonegap模块工厂函数的代码,而myphonegap/builer的并没有执行,因为只有myphonegap模块被请求了。
window.myphonegap = require('myphonegap'); window.myphonegap.Hello("wen");
myphonegap.js 源码
;(function(){
var require,//myphonegap内部的工具函数,用来导入相关的模块 define;//在myphonegap注册相关的模块 //通过一个立即调用的匿名函数,来给require和define赋上实际的函数 (function(){ var modules={}; // 模块数组,添加模块类似给这个对象添加了属性,模块名为属性名,模块对象为属性值,或者说是键值对 build = function(module){ //根据模块对象构造模块导出对象,模块导出对象存储在modules这个对象数组内 var factory = module.factory; module.exports = {}; //给当前模块加入了一个exports属性 delete module.factory; //删除了module的属性 factory(require,module.exports,module); //构建导出模块,module.exports是传出参数(实参,引用传递) return module.exports; } require = function(id){ //根据模块名称/id请求模块对象,如果是第一次请求,就构建对象 if(!modules[id]){ throw "module " + id + " not found!"; } return modules[id].factory?build(modules[id]):modules[id].exports; } define = function(id,factory){ //定义模块,模块名称、构建模块对象的工厂方法。 if(modules[id]){ throw "module " + id + " is exist!"; } modules[id] = { //定义模块对象,左边的值为属性名,右边的值为传入的参数 id:id, factory:factory }; } })();
//注册myphonegap模块
define("myphonegap", function(require, exports, module){
console.info("create myphonegap module");
var myphonegap = {
Hello:function(name){
console.info("hello, "+name +" !");
}
};
module.exports = myphonegap;
});
//注册myphonegap/builder模块
define("myphonegap/builder", function(require, exports, module) {
});
define("myphonegap/channel",function(require,exports,module){
});
//注册myphonegap/common模块
//配置对象,将公共模块组织起来
define("myphonegap/common",function(require,exports,module){
});
define("myphonegap/exec", function(require, exports, module) {
});
//注册myphonegap/platform模块
define("myphonegap/platform", function(require, exports, module){
});
// 这里省略了其它插件的注册
//注册myphonegap/utils模块
define("myphonegap/utils", function(require, exports, module){
});
(function (context) {
}(window));
//所有模块注册完之后,再导入myphonegap至全局环境中
window.myphonegap = require('myphonegap'); window.myphonegap.Hello("wen");
})();
相关文章推荐
- 5 (phonegap源码分析)通用配置/构建模块(common builder)
- 6 (phonegap源码分析)主模块的实现 (myphonegap)
- 4(phonegap源码分析)通道模块的事件订阅机制(channel)
- 7 (phonegap源码分析) 平台相关模块和初始化(platform)
- nginx源码分析-nginx模块定义和各大模块的上下文模块定义
- DSS源码分析--对RTSP请求的状态机处理机制
- Android 5.1 Contacts源码分析(一):Contacts模块文件结构
- spring源码分析之spring-jdbc模块详解
- Volley -- 网络请求源码分析
- tomcat6源码分析一(核心模块分析)
- tomcat源码---->request的请求参数分析
- Spark源码分析之Scheduler模块(TaskScheduler)
- Android FM模块学习之四源码分析(八)
- Mybatis工作机制源码分析—一次insert请求处理流程
- U-BOOT介绍以及disk模块源码分析
- 《易道客》源码剖析之二:模块的定义和使用
- layui源码详细分析系列之文件上传模块
- Spark Scheduler模块源码分析之DAGScheduler
- Glusterfs之rpc模块源码分析(中)之Glusterfs的rpc模块实现(3)
- apache kafka系列之源码分析走读-kafka内部模块分析