模块化

作者: 转移到CSDN名字丹丹的小跟班 | 来源:发表于2021-03-29 18:16 被阅读0次
    1.CommonJS

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

    commonJS用同步的方式加载模块。在服务端,模块文件都存在本地磁盘,读取非常快,所以这样做不会有问题。但是在浏览器端,限于网络原因,更合理的方案是使用异步加载,所以在浏览器端一般就不使用commonJS了

    (2)特点
    所有代码都运行在模块作用域,不会污染全局作用域。
    模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
    模块加载的顺序,按照其在代码中出现的顺序。
    (3)基本语法
    暴露模块:module.exports = value或exports.xxx = value
    引入模块:require(xxx),如果是第三方模块,xxx为模块名;如果是自定义模块,xxx为模块文件路径

    此处我们有个疑问:CommonJS暴露的模块到底是什么? CommonJS规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的module.exports属性。

    (4)模块的加载机制
    CommonJS模块的加载机制是,输入的是被输出的值的拷贝。也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。这点与ES6模块化有重大差异(下文会介绍),请看下面这个例子:

    2.AMD

    (1)概述
    CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作。AMD规范则是非同步加载模块,允许指定回调函数。由于Node.js主要用于服务器编程,模块文件一般都已经存在于本地硬盘,所以加载起来比较快,不用考虑非同步加载的方式,所以CommonJS规范比较适用。但是,如果是浏览器环境,要从服务器端加载模块,这时就必须采用非同步模式,因此浏览器端一般采用AMD规范。此外AMD规范比CommonJS规范在浏览器端实现要来着早。require.js就是依据此规范完成的。
    (2)AMD规范基本语法
    定义没有依赖的模块

    define(function(){
       return 模块
    })
    

    定义有依赖的模块

    define(['module1', 'module2'], function(m1, m2){
       return 模块
    })
    

    引入并使用模块

    require(['module1', 'module2'], function(m1, m2){
       使用m1/m2
    })
    
    3.CMD

    (1)概述
    CMD规范专门用于浏览器端,模块的加载是异步的,模块使用时才会加载执行。CMD规范整合了CommonJS和AMD规范的特点。在 Sea.js 中,所有 JavaScript 模块都遵循 CMD模块定义规范。
    (2)CMD规范基本语法

    定义没有依赖的模块

    define(function(require, exports, module){
      exports.xxx = value
      module.exports = value
    })
    

    定义有依赖的模块

    define(function(require, exports, module){
      //引入依赖模块(同步)
      var module2 = require('./module2')
      //引入依赖模块(异步)
        require.async('./module3', function (m3) {
        })
      //暴露模块
      exports.xxx = value
    })
    

    引入使用模块:

    fine(function (require) {
      var m1 = require('./module1')
      var m4 = require('./module4')
      m1.show()
      m4.show()
    })
    

    cmd和amd区别

    • 对于依赖的模块 CMD 是延迟执行,而 AMD 是提前执行(不过 RequireJS 从 2.0 开始,也改成可以延迟执行。 )
    • CMD 推崇依赖就近,AMD 推崇依赖前置。
    • AMD 的 api 默认是一个当多个用,CMD 严格的区分推崇职责单一,其每个 API 都简单纯粹。例如:AMD 里 require 分全局的和局部的。CMD 里面没有全局的 require,提供 seajs.use() 来实现模块系统的加载启动。
    4.ES6模块化

    (1)概述
    ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。
    (2) ES6模块化语法
    export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

    var basicNum = 0;
    var add = function (a, b) {
        return a + b;
    };
    export { basicNum, add };
    /** 引用模块 **/
    import { basicNum, add } from './math';
    function test(ele) {
        ele.textContent = add(99 + basicNum);
    }
    

    如上例所示,使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。

    // export-default.js
    export default function () {
      console.log('foo');
    }
    // import-default.js
    import customName from './export-default';
    customName(); // 'foo'
    

    ES6 模块与 CommonJS 模块的差异
    它们有两个重大差异:

    • CommonJS 模块输出的是一个值的拷贝(require.js和sea.js也是),ES6 模块输出的是值的引用。
    • CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
    总结
    • CommonJS规范主要用于服务端编程,加载模块是同步的,这并不适合在浏览器环境,因为同步意味着阻塞加载,浏览器资源是异步加载的,因此有了AMD CMD解决方案。
    • AMD规范在浏览器环境中异步加载模块,而且可以并行加载多个模块。不过,AMD规范开发成本高,代码的阅读和书写比较困难,模块定义方式的语义不顺畅。
    • CMD规范与AMD规范很相似,都用于浏览器编程,依赖就近,延迟执行,可以很容易在Node.js中运行。不过,依赖SPM 打包,模块的加载逻辑偏重
    • ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。

    相关文章

      网友评论

          本文标题:模块化

          本文链接:https://www.haomeiwen.com/subject/jlnbhltx.html