CommonJs和ESModule 区别

150 阅读4分钟

ComonmJs

关键词:

社区标准

使用函数实现

仅node环境支持

动态依赖(需要代码运行后才能确认依赖)

动态依赖是同步执行的

原理(很重要,要认真理解代码备注)

// require函数的伪代码
function require(path) {
  if (该模块有缓存吗) {
    return 该模块的缓存;
  }
  function _run(exports, require, module, __filename, __dirname) {
    //这里可以在模块中使用arguments.length,或者直接调用参数验证
    // 模块代码会放到这里
  }
​
 //创建一个模块的对象
  var module = {
    exports: {}
  }
}
​
_run.call(
    //改变this指向 指向module.exports
    module.exports,
    //传入五个参数
    module.exports,
    require,
    modeule,
    模块路径,
    模块所在目录
)

补充一下

可能出现的面试题

exports = 'b'
this.a = 'a'
module.exports = {
    d:'d'
}

这里的this module module.export 再一个模块中是一个东西 其中module.export是返回的结果,

如果将返回结果重新赋值成新的对象 那么模块返回的将会是一个新的对象

输出结果:

{ d: 'd' }

ES Module

关键词:

官方标准

使用新语法实现

所有环境均支持

同时支持静态依赖和动态依赖

静态依赖: 在代码运行前也就是编译阶段就要确定依赖关系 import

动态依赖是异步的 import(‘./1.js’).then((m)=>{console.log(m)}) 或者用函数的形式()=>import('./')动态路由中

符号绑定

对于符号绑定

//2.js
export var count = 0;
export function increase() {
    count++
}
//1.js
import { count as c, increase } from './a.js'console.log(c)
increase()
console.log(c)

输出结果:

0
1

其实就是暴露的时候是地址传递了

一些面试题

CMJ和es6模块的区别是什么

CommonJS (CJS) 和 ES6 模块是两种不同的JavaScript模块系统。它们有几个主要的区别:

  1. 导入方式和语法: 在CommonJS中,我们使用require函数来导入模块。在ES6中,我们使用import语句来导入模块。例如: const module = require('module')VS import module from 'module'
  2. 导出方式和语法: 在CommonJS中,我们使用module.exports来导出模块。在ES6中,则使用export语句来导出模块。例如:module.exports = {} VS export default {}
  3. 动态和静态加载: CommonJS 支持动态加载,即可以在运行时决定加载哪个模块,模块引入的位置也可以在代码的任何地方。而 ES6 模块是静态的,它需要所有导入在编译阶段就确定,也就是说所有的导入必须在模块的顶部。
  4. 值的加载方式: CommonJS模块输出的是一个值的拷贝。也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。而ES6模块输出的是值的引用。也就是说,ES6的import命令输入的都是被输出值的动态只读视图(只读引用),原始值改变,import命令加载的值也会随之改变。
  5. this的指向: 在 CommonJS 模块中,顶层的this指向当前模块(在严格模式下是undefined)。在 ES6 模块中,顶层的this指向undefined
  6. 循环依赖处理: ES6 模块与 CommonJS 的循环依赖解决方案有所不同,CommonJS 在遇到循环依赖时可能会导出不完整的对象或者空对象,而 ES6 则是延迟执行。

export和export default 的区别是社么

在JavaScript ES6模块系统中,exportexport default是两种不同的导出方式,主要的区别在于是否需要使用花括号来引入导出的模块以及每个模块中export default只能有一个,export可以有多个。以下是详细的区别:

  1. export default:每个模块只能有一个export default。当其他模块导入这个模块时,不需要知道导出变量的名称,可以自由命名。

例子:

// module.js
export default function myFunc() { }
​
// app.js
import myFunction from './module.js'; // 导入的名字可以自由选择
  1. export:一个模块可以有多个export。当其他模块导入该模块时,需要用花括号 {} 包裹所要导入的变量(多个变量用逗号分割),且名称必须和导出的名称一致。

例子:

// module.js
export function func1() { }
export function func2() { }
​
// app.js
import { func1, func2 } from './module.js'; // 导入的名字必须和导出的名字一致
  1. 同时使用exportexport default:一个模块中既可以有export default也可以有export

例子:

// module.js
export function func1() { }
export default function func2() { }

// app.js
import func2, { func1 } from './module.js'; // 要先导入export default对应的成员,然后再import export对应的成员

注意,如果使用 export default 导出某个变量,但在导入时候仍然采用 import { varname } from './module.js' 的方式,将会导入失败。因为 export default 导出的变量不具备可以配合{}解构的特性。