[JavaScript] JavaScript进阶系列 - 使用require高效组织代码结构
前言
实际项目中,使用JavaScript开发面临着一个很大的问题,就是代码的可控性差。随着项目的进展,JavaScript代码量也许会爆炸式增长,如果不加以控制,那么潜在的问题将越积越多。在此说明下,很多人认为JavaScript难登大雅之堂,就是一门简简单单的脚本语言,觉得能用就行,不屑于深入理解。这也是为什么国内的很多项目,JavaScript部分混乱,安全性可扩展性很差的原因。其实JavaScript真的不简单。
使用require管理代码结构
require代码如下:
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。
下面我们通过一个例子来好好的理解下。
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