js 模块化规范

模块化规范无规范时通用做法

IIFE模式:匿名函数自调用(闭包)

  • 作用: 数据是私有的, 外部只能通过暴露的方法操作

  • 编码: 将数据和行为封装到一个函数内部, 通过给window添加属性来向外暴露接口

    (function usePopup(store, params) {
      const key = Symbol();
      const { type, kind } = params;
      function showPopup(extData) {
        // do something
      }
      windows.myModule = {
        showPopup,
    	}
    })(window)
    
  • 如果当前这个模块依赖另一个模块怎么办?

    ​ 通过参数传递,但是要考虑script的引入顺序

    (function usePopup(store, params) {
      const key = Symbol();
      const { type, kind } = params;
      function showPopup(extData) {
        // do something
      }
      windows.myModule = {
        showPopup,
    	}
    })(window, jQuery)
    
  • 好处

    • 避免命名冲突(减少命名空间污染)
    • 更好的分离, 按需加载
    • 更高复用性
    • 高可维护性
  • 问题

    • 请求过多
    • 依赖模糊
    • 难以维护

模块化规范

  • CommonJS

    Node 应用由模块组成,采用 CommonJS 模块规范。每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。在服务器端,模块的加载是运行时同步加载的;在浏览器端,模块需要提前编译打包处理。

    • 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。

    • 同步加载

    • 暴露模块:module.exports = valueexports.xxx = value

    • 引入模块:require(xxx),如果是第三方模块,xxx为模块名;如果是自定义模块,xxx为模块文件路径

    • CommonJS模块的加载机制是,输入的是被输出的值的拷贝。也就是说,一旦输出一个值,模块内部的变化就影响不到这个值

  • AMD

    CommonJS解决了模块化的问题,但这种同步加载方式并不适合于浏览器端

    它采用异步方式加载模块,模块的加载不影响它后面语句的运行。
    这里异步指的是不堵塞浏览器其他任务(dom构建,css渲染等),而加载内部是同步的(加载完模块后立即执行回调)

    • AMD也采用require命令加载模块,但是不同于CommonJS,它要求两个参数:

      // require([module], callback)
      
      require(['math'], function(math) {
        math.add(2, 3);
      })
      
    • 模块书写必须使用特定的define()函数来定义。如果一个模块不依赖其他模块,那么可以直接写在define()函数之中。

      // define(id?, dependencies?, factory);
      
      // 加载模块的时候,就会先加载dependenceModule模块
      define(['dependenceModule'], function(dependenceModule) {
          // ...
      })
      

      当有多个依赖时,就将所有的依赖都写在define()函数第一个参数数组中,**所以说AMD是依赖前置的。**这不同于CMD规范,它是依赖就近的。

  • CMD

    CMD与AMD基本类似,推崇依赖就近,延迟执行

    // CMD
    define(function(require, exports, module) {
      var a = require('./a');
      a.doSomething();
      var b = require('./b');
      b.doSomething();
    })
    
    // AMD
    define(['a', 'b'], function(a, b) {
      a.doSomething();
      b.doSomething();
    })
    
  • ES6模块化

    • ES6 模块输出的是值的引用,输出接口动态绑定,而 CommonJS 输出的是值的拷贝
    • ES6 模块编译时(js无编译动作,理解为解析时)执行,而 CommonJS 模块总是在运行时加载
    • 重点阐述与CommonJs的区别

      ES6
      1. ES6模块中的值属于动态只读引用。
      2. 对于只读来说,即不允许修改引入变量的值,import的变量是只读的,不论是基本数据类型还是复杂数据类型。当模块遇到import命令时,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。
      3. 对于动态来说,原始值发生变化,import加载的值也会发生变化。不论是基本数据类型还是复杂数据类型。
      4. 循环加载时,ES6模块是动态引用。只要两个模块之间存在某个引用,代码就能够执行。
      CommonJS
      1. 对于基本数据类型,属于复制。即会被模块缓存。同时,在另一个模块可以对该模块输出的变量重新赋值。
      2. 对于复杂数据类型,属于浅拷贝。由于两个模块引用的对象指向同一个内存空间,因此对该模块的值做修改时会影响另一个模块。
      3. 当使用require命令加载某个模块时,就会运行整个模块的代码。
      4. 当使用require命令加载同一个模块时,不会再执行该模块,而是取到缓存之中的值。也就是说,CommonJS模块无论加载多少次,都只会在第一次加载时运行一次,以后再加载,就返回第一次运行的结果,除非手动清除系统缓存。
      5. 当循环加载时,脚本代码在require的时候,就会全部执行。一旦出现某个模块被"循环加载",就只输出已经执行的部分,还未执行的部分不会输出。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值