[JavaScript] JavaScript进阶系列 - 使用require高效组织代码结构

前言


  实际项目中,使用JavaScript开发面临着一个很大的问题,就是代码的可控性差。随着项目的进展,JavaScript代码量也许会爆炸式增长,如果不加以控制,那么潜在的问题将越积越多。在此说明下,很多人认为JavaScript难登大雅之堂,就是一门简简单单的脚本语言,觉得能用就行,不屑于深入理解。这也是为什么国内的很多项目,JavaScript部分混乱,安全性可扩展性很差的原因。其实JavaScript真的不简单。

 

使用require管理代码结构


  require代码如下:

 1 var require, define;
 2 (function() {
 3   var modules = {};
 4   
 5   function build(module) {
 6     var factory = module.factory;
 7     module.exports = {};
 8     delete module.factory;
 9     factory(require, module.exports, module);
10     return module.exports;
11   }
12   
13   require = function(id) {
14     if (!modules[id]) {
15       throw 'module ' + id + 'not found';
16     }
17     return modules[id].factory ? build(modules[id]) : modules[id].exports;
18   };
19   
20   define = function(id, factory) {
21     if (modules[id]) {
22       throw 'module ' + id + ' already defined';
23     }
24     
25     modules[id] = {
26       id: id,
27       factory: factory
28     };
29   };
30   
31   define.remove = function(id) {
32     delete modules[id];
33   }
34   
35 })();

  不管你相不相信,短短的35行代码完全可以帮助你管理好你的代码。下面我们来详细的解读下这段代码,

  1. 第 1 行 定义了两个全局变量 require 和 define

    define: 用于定义代码模块,就像Java里面的类,封装了方法和属性,定义的代码模块中封装了一些列的方法和属性,以便调用。

    require: 用于调用封装好的代码模块,就像Java里面在一个类中,可以调用另一个类中的属性和方法,require就用于创建一个模块的对象,供其他模块调用它里面的方法和属性。

  2. 第 2 ~ 35 行 详细给出了define, require以及define.remove三个方法的逻辑。

  3. 第 3 行 定义一个局部变量 modules ,用于缓存所定义的所有模块。

  4. 第 20 行 定义了 define 方法, 此处有两个参数 id 和 factory,

    id: 该参数的类型是String, 用于定义模块的组织结构,必需唯一,你可以定义为 "cnblogs/utils" 或者 "cnblogs/view"等

    factory: 该参数的类型是Function, 用于定义模块具体的代码实现

  5. 第 31 行 定义了 define.remove 方法, 该方法用于删除某个模块

  6. 第 13 行 定义了 require 方法, 该方法用于加载某个模块

  7. 第 5 行定义了 私有方法 build ,第一次看这个方法你会觉得很奇怪,里面的 factory, exports等会让你感到丈二和尚摸不着头脑,我先简要介绍下,factory就是 define 方法中的参数 factory, exports在这儿你可以理解为需要分享出来的 API。

  下面我们通过一个例子来好好的理解下。

 1 define('cnblogs/utils', function(require, exports, module) {
 2   var utils = exports;
 3   
 4   utils.isArray = function(a) {
 5     return Object.prototype.toString.call(a) == '[object Array]';
 6   };
 7   
 8   utils.alert = function(msg) {
 9     if (alert) {
10       alert(msg);
11     } else if (console && console.log) {
12       console.log(msg);
13     }
14   };
15 });
16 
17 define('cnblogs/view', function(require, exports, module) {
18   var utils = require('cnblogs/utils');
19   var views = {
20     showWebView: function() {
21       utils.alert('Show WebView...');
22     },
23     hideWebView: function() {
24       utils.alert('Hide WebView...');
25     }
26   };
27   module.exports = views;
28 });
29 
30 var cnBlogsView = require('cnblogs/view');
31 cnBlogsView.showWebView();
32 
33 /*
34 define.remove('cnblogs/view');
35 var cnBlogsView1 = require('cnblogs/view');
36 cnBlogsView1.showWebView();
37 */

  备注:

    该例子中我们创建了两个模块"cnblogs/utils"和"cnblogs/view"。"cnblogs/utils" 用于定义项目中的一个工具方法,该模块类似于Java中的工具类。"cnblogs/view"用于定义项目中和视图相关的公共方法,并且在该模块中调用"cnblogs/utils"模块中的"alert"方法。

  讲解:

  1. 第 1 ~ 15 行使用define方法定义"cnblogs/utils"模块, 第 2 ~ 14  行是define方法 factory 参数的函数体内容,该factory函数定义了3个参数

  require: 可看做全局变量require

  exports: 类型为Object,用于封装需要分享出来的方法和属性

  module: 可看作该模块本身的一个引用

  第 2 行 var utils = exports; 表明utils对象将被exports出来,例如第 18 行, var utils = require('cnblogs/utils'); 该utils就是exports对象即第 2 行中的utils对象。

  2. 第 17 ~ 28 行定义了 "cnblogs/view" 模块,此处我们重点看下第 18 行和第 27 行,第 18 行使用require方法获取"cnblogs/utils"模块信息,第 27 行 module.exports = views; 等价于使用 var views = exports;

  3. 第 30 ~ 37 行用于测试。

 

作者信息:

QQ: 1321518080

Email: hucaijun520.ok@163.com

posted @ 2012-10-12 16:24  书生小C  阅读(2005)  评论(5编辑  收藏  举报