• Javascript 中的 CJS, AMD, UMD 和 ESM是什么


    ES6之前,JS一直没有自己的模块体系,这一点对于大型项目的开发很不友好,所以社区出现了CommonJSAMD(本人不熟悉),CommonJS主要是用于服务器(Node),AMD主要是用于浏览器

    但是ES6引入了ESM,到此,JS终于有了自己的模块体系,基本上可以完全取代CJS和AMD。

    下面简单总结一下ESM以及ESM和CJS的区别

    一、CJS

    CJS 是 CommonJS 的缩写。主要用于服务器端,主要使用如下:

    // 导出
    const obj = {a: 1};
    module.exports = obj;

    // 引入
    const obj = require('./test.js');

    二、ESM

    ESM是ESModule,是ECMAScript自己的模块体系,是 Javascript 提出的实现一个标准模块系统的方案,于ES6引入, 代表 ES 模块。主要使用如下:

    // 导出:export命令
    export const obj = {name: 'E1e'};
     
    // 默认导出 export default命令
    export default {name: 'E1e'};
     
     
    // 引入接口:import命令
     
    // 引入普通导出
    import { obj } from './test.js';
     
    // 引入默认导出
    import obj from './test.js';

    可以在 HTML 中调用,只要如下

    <script type="module">
      import {func1} from 'my-lib';
     
      func1();
    </script>

    在很多现代浏览器可以使用

    它兼具两方面的优点:具有 CJS 的简单语法和 AMD 的异步

    三、区别

     commonJs 和 esModule 的区别

    使用方式不同(以上);CJS 不能在浏览器中工作。它必须经过转换和打包

    commonJs是被加载的时候运行,esModule是编译的时候运行

    commonJs输出的是值的浅拷贝,esModule输出值的引用

    commentJs具有缓存。在第一次被加载时,会完整运行整个文件并输出一个对象,拷贝(浅拷贝)在内存中。下次加载文件时,直接从内存中取值

    commonJs 输出值拷贝

    /*************** a.js**********************/
    let count = 0
    exports.count = count; // 输出值的拷贝
    exports.add = ()=>{
        //这里改变count值,并不会将module.exports对象的count属性值改变
        count++;
    }
     
    /*************** b.js**********************/
    const { count, add } = require('./a.js')
    //在支持es6模块的环境下等同于
    import { count, add } from './a.js'
     
    console.log(count) //0
    add();
    console.log(count)//0

    esModule 输出值引用

    /*************** a.js**********************/
    export let count = 0;//输出的是值的引用,指向同一块内存
    export const add = ()=>{
        count++;//此时引用指向的内存值发生改变
    }
    /*************** b.js**********************/
    import { count, add } from './a.js'
     
    console.log(count) //0
    add();
    console.log(count)//1

    ES6 模块加载 CommonJS 模块

    module.exports 等同于 export default 可以用 import 引入

    CommonJS 模块加载 ES6 模块

    CommonJS 模块加载 ES6 模块,不能使用require命令,而要使用import()函数。

    exports 和 module.exports 的区别

    module.exports 默认值为{}

    exports 是 module.exports 的引用

    exports 默认指向 module.exports 的内存空间

    require() 返回的是 module.exports 而不是 exports

    若对 exports 重新赋值,则断开了 exports 对 module.exports 的指向

    引用:

    require 和 import 都可引用

    module.exports
    //foo.js
    exports.foo="foo"
    //等同于
    module.exports.foo="foo"
     
    //bar.js
    const { foo } = require('./foo.js')
    console.log(foo);//'foo'
     
    exports
    //foo.js
    exports={
        foo: 'foo'
    }
     
    //bar.js
    const { foo } = require('./foo.js')
    //reuqire 返回的是 module.exports 对象, 默认为 {}
    console.log(foo);//undefined
     

    四、其他模式

    AMD

    AMD 代表异步模块定义。下面是一个示例代码

    define(['dep1', 'dep2'], function (dep1, dep2) {
        //Define the module value by returning a value.
        return function () {};
    });

    或者

    // "simplified CommonJS wrapping" https://requirejs.org/docs/whyamd.html
    define(function (require) {
        var dep1 = require('dep1'),
            dep2 = require('dep2');
        return function () {};
    });

    AMD 是异步(asynchronously)导入模块的(因此得名)

    一开始被提议的时候,AMD 是为前端而做的(而 CJS 是后端)

    AMD 的语法不如 CJS 直观。我认为 AMD 和 CJS 完全相反

    UMD

    UMD 代表通用模块定义(Universal Module Definition)。

    (function (root, factory) {
        if (typeof define === "function" && define.amd) {
            define(["jquery", "underscore"], factory);
        } else if (typeof exports === "object") {
            module.exports = factory(require("jquery"), require("underscore"));
        } else {
            root.Requester = factory(root.$, root._);
        }
    }(this, function ($, _) {
        // this is where I defined my module implementation
     
        var Requester = { // ... };
     
        return Requester;
    }));

    在前端和后端都适用(“通用”因此得名)

    与 CJS 或 AMD不同,UMD 更像是一种配置多个模块系统的模式。

    当使用 Rollup/Webpack 之类的打包器时,UMD 通常用作备用模块

  • 相关阅读:
    Selenium IDE
    selenium简介
    Java程序要操作数据库,一定要使用JDBC技术吗?
    JDBC几个接口分区叫什么?它们分别有什么用?
    JDBC的全称是什么?
    什么时候使用session?什么时候使用application?
    内置对象session和application的作用是什么?
    修改表单中为什么要使用隐藏域?
    如何创建一个不能修改的属性?
    如何修改属性?
  • 原文地址:https://www.cnblogs.com/h-c-g/p/15397942.html
Copyright © 2020-2023  润新知