es6 Module和commonjs的区别

1,072 阅读2分钟

总结自coderwhy的nodejs教程

common.js

  • 导入导出是值的引用,如果导出的是一个基本数据类型值,那么导出文件改变该值,然后导入文件该变量的值也不会变。

  • 他是通过require 函数来导入的,只有在执行js代码才会知道模块的依赖关系。

  • 代码是同步执行的。

  • 模块多次引入,只会加载一次。每个module内部会存在一个loaded来确定是否被加载过

image.png

  • 代码循环引入的时候,深度优先来加载模块。然后再广度优先。

下面一个例子执行顺序:main,aaa,ccc,ddd,eee,bbb(这个bbb加载是通过main模块加载的。)

image.png

下面这个例子主要是为了说明common.js导出的基本数据类型,导入导出文件修改,都不会相互影响。但是对于引用数据类型就会相互影响。

    // foo.js
    let age = 'ppp';
    const obj = {
      name: 'llm'
    }

    setTimeout(() => {
      age = 10000;
    }, 1000)


    setTimeout(() => {
      console.log("导出文件obj.name", obj.name)//zh
    }, 2000)

    exports.age = age;
    exports.obj = obj;
    // bar.js
    const bar = require("./foo.js")
    
    setTimeout(() => {
      console.log("导入的文件age", bar.age)// ppp, 不会输出10000
    }, 2000)


    setTimeout(() => {
      bar.obj.name = "zh"
    }, 1000)

es6 Module

  • 它是通过关键字来导入导出的。(import, export)

  • 异步加载,相当于加上了async属性。<script src="" type="module" async ></script>

  • 模块的相互依赖,在js代码编译的时候就知道了。

  • 导入文件和导出文件中的变量是实时绑定的。 注意:下面这个例子需要在服务器端启动。不然会报错。

这个例子就是想说明导出的基本数据类型在导出文件中修改可以,并且是实时绑定到导入文件中的, 但是导入文件不能修改基本数据类型。

    // foo.js
    let name = "zh";
    const obj = {
      name: 'llm'
    }

    setTimeout(() => {
      console.log("导出的obj.name", obj.name) // pppp
    }, 2000)

    setTimeout(() => {
      name = 'qqqq'
    })

    export {
      name,
      obj
    }
//bar.js
    import * as bar from './foo.js'

    console.log("bar执行")
    console.log(bar.name)
    // setTimeout(() => {
    //   bar.name = "pppp" //这里是不能修改导入的普通类型的变量的。因为在js内部,他自己通过const重新声明这个变量,做到实时绑定。
    // }, 1000)


    setTimeout(() => {
      bar.obj.name = "pppp" //但是可以修改导入的普通类型的变量的。
    }, 1000)



    setTimeout(() => {
      console.log("导出文件改变后的值", bar.name)// qqqq
    }, 2000)

    console.log("name=====", bar.name)
    console.log("obj.name======", bar.obj.name)
<script src="./bar.js" type="module"></script>

image.png

image.png