美文网首页
CommonJS 和 ES Module 区别

CommonJS 和 ES Module 区别

作者: 硅谷干货 | 来源:发表于2022-03-12 17:35 被阅读0次

    测试环境
    node v13.12.0

    先上结论

    img

    1. 对导入值的验证

    commonJS

    // mod.js
    let count = 1;
    let friends = ['夏洛'];
    
    function plusCount() {
        count++
    };
    
    function plusYuanhua() {
        friends.push('袁华');
    }
    
    setInterval(() => {
        console.log('mod.js 每秒打印 - count', count);
        console.log('mod.js 每秒打印 - friends', friends);
    }, 1000);
    
    module.exports = {
        count,
        friends,
        plusCount,
        plusYuanhua,
    }
    
    
    // index.js
    const mod = require('./mod.js');
    
    console.log('index.js 初次导入 - mod.count', mod.count);
    console.log('index.js 初次导入 - mod.friends', mod.friends);
    
    mod.plusCount();
    mod.plusYuanhua();
    
    console.log('index.js 执行 mod.plusCount/plusYuanhua 后 - mod.count', mod.count);
    console.log('index.js 执行 mod.plusCount/plusYuanhua 后 - mod.friends', mod.friends);
    
    setTimeout(() => {
        mod.count = 3;
        console.log('index.js 延时2s - mod.count', mod.count);
        console.log('index.js 延时2s - mod.friends', mod.friends);
    }, 2000)
    
    /*
    index.js 初次导入 - mod.count 1
    index.js 初次导入 - mod.friends [ '夏洛' ]
    
    index.js 执行 mod.plusCount/plusYuanhua 后 - mod.count 1
    index.js 执行 mod.plusCount/plusYuanhua 后 - mod.friends [ '夏洛', '袁华' ]
    
    mod.js 每秒打印 - count 2
    mod.js 每秒打印 - friends [ '夏洛', '袁华' ]
    
    mod.js 每秒打印 - count 2
    mod.js 每秒打印 - friends [ '夏洛', '袁华' ]
    
    index.js 延时2s - mod.count 3
    index.js 延时2s - mod.friends [ '夏洛', '袁华' ]
    
    mod.js 每秒打印 - count 2
    mod.js 每秒打印 - friends [ '夏洛', '袁华' ]
    */
    

    ES Module

    Node 13.2 增加了对 ES Module 的支持,为使 node 识别 ES Module,你需要做如下之一

    1. 更改 .js.mjs,并使用 node index.mjs
    2. package.json添加字段"type": "module",如此所有 .js 均被识别为 ES Module
    // index.mjs
    import { counter } from './mod.mjs'
    counter = {}; // TypeError: Assignment to constant variable.
    console.log('a.js-1', counter)
    
    // mod.mjs
    export let counter = {
        count: 1
    }
    setInterval(() => {
        console.log('modB.js-1', counter.count)
    }, 1000)
    

    可见 import 为只读引入,如此,mod.mjs 中 count 变化会及时的反应在 index.mjs 中

    2. 模块导入,它们做了什么?

    commonJS

    // index.js
    let a = require('./modA.js')
    let b = require('./modB.js')
    console.log('index.js-1', '执行完毕', a.done, b.done)
    
    // modA.js
    exports.done = false
    let b = require('./modB.js')
    console.log('modA.js-1', b.done)
    exports.done = true
    console.log('modB.js-2', '执行完毕')
    
    // modB.js
    exports.done = false
    let a = require('./modA.js')
    console.log('modB.js-1', a.done)
    exports.done = true
    console.log('modB.js-2', '执行完毕')
    
    /*
    modB.js-1 false
    modB.js-2 执行完毕
    modA.js-1 true
    modB.js-2 执行完毕
    index.js-1 执行完毕 true true
    */
    

    执行顺序是这样的:

    1. node 执行 index.js 文件,发现 require('./modA.js'),暂停 index.js 代码执行,进入 modA 模块
    2. 在 modA 中发现 require('./modB.js'),暂停 modA 代码执行,将已执行的部分 modA 代码缓存,随后进入 modB 模块
    3. 在 modB 中发现require('./modA.js')提取已缓存的部分 modA (因为 modA 代码全部执行完),执行所有的 modB 代码,完毕后,缓存 modB 执行结果,执行栈返回至 modA
    4. 执行 modA 剩余代码,完毕后,缓存 modA,执行栈返回 index.js
    5. 在 index.js 发现 require('./modBjs')提取已有的 modB 缓存,执行剩余代码

    ES Module

    // index.mjs
    console.log("before import mod")
    import { b } from "./mod.mjs"
    console.log("b is " + b)
    export let a = b + 1;
    
    // mod.mjs
    console.log("before import index")
    import { b } from "./index.mjs"
    console.log("b is " + b)
    export let a = b + 1;
    
    /*
    before import a
    a is undefined
    before import b
    b is NAN
    */
    

    这里的顺序也很简单,

    1. 进入 index.mjs ,提升 import('./modB.mjs') 语句至顶部,最先执行,进入 modB
    2. 提升 提升 import('./index.mjs') 语句至顶部,发现已经执行过 index.mjs,此处将从 index 导入的内容当作 { },执行剩余代码。完毕后,执行栈返回 index.mjs
    3. 执行剩余代码

    参考资料:
    CommonJS模块和ES6模块的区别 - 凯斯keith - 博客园
    ES6中循环引用的坑 | 杨光的笔记

    相关文章

      网友评论

          本文标题:CommonJS 和 ES Module 区别

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