JavaScript中的各种规范差异

358 阅读2分钟

一、AMD, CommonJS, CMD, UMD, ES6 分析

插一句:Rollup 是一个打包ES Module 的工具

  • CommonJS 主要运行于服务器

    • 该规范指出:一个文件就是一个模块

    • nodejs是主要实践者

    • 同步加载,在服务器端没问题,在浏览器端异步加载是更好的方案

    • 有四个主要的环境变量:

      • module
      • exports:module.exports 命令用于规范模块的对外接口,输出后就不能改变
      • require:用于输入其他模块提供的功能
      • global
    // 模块 a.js
    const name = 'qiufeng'module.exports = {
        name,
        github: 'https://github.com/hua1995116'
    }
    // 模块 b.js
    // 引用核心模块或者第三方包模块,不需要写完整路径
    const path = require('path');
    // 引用自定义模块可以省略.js
    const { name, github } = require('./a');
    ​
    console.log(name, github, path.basename(github));
    // 输出 qiufeng https://github.com/hua1995116 hua1995116
    
  • AMD(Asynchronous Module Definition)异步加载模块

    • 异步模式加载模块,模块的加载不影响后边语句的执行,所有依赖这个模块的语句,都在回调函数里。

    • requireJS是最佳实践者

    • 依赖前置,提前执行

    • 语法不直观, 没用commonJS便于书写

    • 主要命令:

      • define:是全局函数,用来定义模块, define(id?, dependencies?, factory)
      • require:用于输入其他模块提供的功能
      • define.amd:是一个对象,此属性的存在来表明函数遵循AMD规范
      • return:规范模块的对外接口
    文件名: foo.js
        define(['jquery'], function ($) {
            // 方法
            function myFunc(){};
    ​
            // 暴露公共方法
            return myFunc;
        });
        
    -------------------------------------------------------------------------------------
    // model1.js
    define(function () {
        console.log('model1 entry');
        return {
            getHello: function () {
                return 'model1';
            }
        };
    });
    // model2.js
    define(function () {
        console.log('model2 entry');
        return {
            getHello: function () {
                return 'model2';
            }
        };
    });
    // main.js
    define(function (require) {
        var model1 = require('./model1');
        console.log(model1.getHello());
        var model2 = require('./model2');
        console.log(model2.getHello());
    });
    <script src="https://cdn.bootcss.com/require.js/2.3.6/require.min.js"></script>
    <script>
        requirejs(['main']);
    </script>
    // 输出结果  
    // model1 entry
    // model2 entry
    // model1
    // model2
    
  • CMD(Common Module Definition)通用模块定义

    • Sea.js 是主要实践者
    • 依赖就近、延迟执行
  • UMD:是AMD和CommonJS的统一规范,可用于多种场景,用法如下

    (function (root, factory) {
        if (typeof define === 'function' && define.amd) {
            // AMD
            define(['jquery'], factory);
        } else if (typeof exports === 'object') {
            // Node, CommonJS之类的
            module.exports = factory(require('jquery'));
        } else {
            // 浏览器全局变量(root 即 window)
            root.returnExports = factory(root.jQuery);
        }
    }(this, function ($) {
        //    方法
        function myFunc(){};
        //    暴露公共方法
        return myFunc;
    }));
    
  • ESM(ES Modules)是ES6提出的标准模块系统

    • 因为是标准,未来很多浏览器支持
    • 兼容在node环境下运行
    • 模块的导入导出,通过 import / export来确定。 可以和commonJS模块混合使用
    • ESM 输出的是值的引用,输出接口动态绑定, 而CommonJS输出的是值的拷贝
    • ESM 模块编译时执行, 而CommonJS模块总是在运行时加载
  • ES6 模块编译时执行会导致有以下两个特点

    • import 优先执行。
    • export 命令会有变量声明提前的效果。

二、 import 和 require的区别

  • 出现的事件地点不同。

    • require/exports 2009 CommonJS
    • import/export 2015 ES6
  • 不同端的使用限制

    • require/exports原生浏览器不支持,但可以使用webpack打包工具转换。
    • import/export
  • require/exports 运行时动态加载,import/export 是静态编译

  • 前者值的拷贝,后者值的引用