• [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

  • 相关阅读:
    Java IO流 简介
    Centos8安装java部署环境
    RedisTemplate
    手把手教windows上安装linux虚拟机及环境配置
    使用Swagger2构建 RESTful API文档
    VMware 安装 Centos 7 虚拟机配置网络
    别再写满屏的 try catch 了
    isEmpty 和 isBlank 的用法区别
    SpringBoot 中必须掌握的45个注解
    数组的栈方法
  • 原文地址:https://www.cnblogs.com/youngC/p/2721538.html
Copyright © 2020-2023  润新知