js基础 ---- 如何实现模块化

一、模块化编程形成的原因

  随着网页的发展 页面逻辑也越来越复杂 所带来的诸如逻辑混乱,页面复杂,可维护性差,全局变量暴露等问题接踵而至

  开发者需求去管理网页的逻辑

  Javascript模块化编程:发者只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块

  现在模块化的编程思想已经越来越普遍

二、模块化编程的优点

  (1)、解决项目中的全局变量污染的问题

  (2)、开发效率高,有利于多人协同开发

  (3)、职责单一,方便代码复用和维护 

  (4)、解决文件依赖问题,无需关注引用文件的顺序

三、模块化的几种规范

  (1)、AMD规范

      含义:它是一个在浏览器端模块化开发的规范,服务器端的规范是CommonJS 模块将被异步加载,模块加载不影响后面语句的运行。所有依赖某些模块的语句均放置在回调函数中

      define() 函数

        AMD规范只定义了一个函数 define,它是全局变量。函数的描述为:

          define(id?, dependencies?, factory)

             id:指定义中模块的名字,可选如果没有提供该参数,模块的名字应该默认为模块加载器请求的指定脚本的名字。如果提供了该参数,模块名必须是“顶级”的和绝对的(不允许相对名字)

        依赖dependencies:是一个当前模块依赖的,已被模块定义的模块标识的数组字面量

                依赖参数是可选的,如果忽略此参数,它应该默认为["require", "exports", "module"]。然而,如果工厂方法的长度属性小于3,加载器会选择以函数的长度属性指定的参数个数调用工厂方法

       工厂方法factory,模块初始化要执行的函数或对象。如果为函数,它应该只被执行一次。如果是对象,此对象应该为模块的输出值

      实例:       

          define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
               exports.verb = function() {
                   return beta.verb();
                     //Or:
                   return require("beta").verb();
               }
           });
  )

   (2)、CommonJS 规范

       CommonJS是服务器端模块的规范,Node.js采用了这个规范。Node.JS首先采用了js模块化的概念

       根据CommonJS规范,一个单独的文件就是一个模块。每一个模块都是一个单独的作用域,也就是说,在该模块内部定义的变量,无法被其他模块读取,除非定义为global对象的属性

       输出模块变量的最好方法是使用module.exports对象

        

        var i = 1;
        var max = 30;

        module.exports = function () {
          for (i -= 1; i++ < max; ) {
              console.log(i);
          }    
          max *= 1.1;
        };

四、模块化的原生实现实现

  (1)、原始写法

      模块就是实现特定功能的一组方法

      只要把不同的函数(以及记录状态的变量)简单地放在一起,就算是一个模块。

        function fn1(){...}

        function fn2(){...}

      fn1 和 fn2 就组成了一个模块 使用的时候直接调用即可

      缺点:"污染"了全局变量,无法保证不与其他模块发生变量名冲突,而且模块成员之间看不出直接关系

  (2)、对象写法

      对第一种方法的一种优化写法 可以把模块写成一个对象,所有的模块成员都放到这个对象里面

      var module1 = new Object{

        _count: 0,

        fn1: function(){...}

        fn2: function(){...}

      }

      调用:module1.fn1()

      但是,这样的写法会暴露所有模块成员,内部状态可以被外部改写。比如,外部代码可以直接改变内部计数器的值

        module1._count = 5

  (3)、立即执行函数写法

      使用 立即执行函数 可以优化对象写法 暴露所有模块成员的问题

      var module1 = (function(){

        var _count = 0;

        var m1 = function(){
          //...
        };

        var m2 = function(){
          //...
        };

        return {
          m1 : m1,
          m2 : m2
        };

      })();

    但是外部也无法读取内部的 _count 变量

      console.info(module1._count); //undefined

  (4)、放大模式

      如果一个模块很大,必须分成几个部分,或者一个模块需要继承另一个模块,这时就有必要采用"放大模式"(augmentation)

      var module1 = (function (mod){

        mod.m3 = function () {
          //...
        };

        return mod;

      })(module1);

      上面的代码为module1模块添加了一个新方法m3(),然后返回新的module1模块

  (5)、宽放大模式

     在浏览器环境中,模块的各个部分通常都是从网上获取的,有时无法知道哪个部分会先加载。如果采用上一节的写法,第一个执行的部分有可能加载一个不存在空对象,这时就要采用"宽放大式"。  

      var module1 = ( function (mod){

        //...

        return mod;

      })(window.module1 || {});

      与"放大模式"相比,"宽放大模式"就是"立即执行函数"的参数可以是空对象

 

posted @ 2020-10-15 11:54  有梦想的咸鱼7  阅读(534)  评论(0编辑  收藏  举报