commonjs与es6 中的模块化机制有什么区别

文章目录

  • 名词解释
  • cjs与es6 module的区别
    • CommonJs导出的是变量的一份拷贝,ES6 Module导出的是变量的绑定(export default 是特殊的)
    • CommonJs是单个值导出,ES6 Module可以导出多个
    • CommonJs是动态语法可以写在判断里,ES6 Module静态语法只能写在顶层
    • CommonJs的 this 和 ES6 Module的 this
  • umd通用

名词解释

  • cjs(commonjs)

    seaJs和node环境下使用的模块化机制。模块必须通过 module.exports 导出对外的变量或接口,通过 require() 来导入其他模块的输出到当前模块作用域中。模块加载是同步的。

  • amd

    伴随requireJs提出的异步加载模块规范。浏览器环境下适用,来解决同步加载的问题。

  • es6 module

    es6提出的模块加载机制。

cjs与es6 module的区别

CommonJs导出的是变量的一份拷贝,ES6 Module导出的是变量的绑定(export default 是特殊的)

cjs中,对象的传递如同a = b 一样,基本类型值传递,对象则引用传递。而es6 module中,如果不用export default去引用,基本类型也是引用传递的。export default的赋值则与a = b 相同。

CommonJs是单个值导出,ES6 Module可以导出多个

一般不提倡使用了export default 还export {a, b, c}。

CommonJs是动态语法可以写在判断里,ES6 Module静态语法只能写在顶层

便于静态检查。如果有循环引用,cjs可以从缓存里读,读到哪里就是哪里。module.exports.a可以改变。而es6则会报错,只能通过函数的方式来读值,因为函数声明会提升到文件顶部。

静态检查有利于摇树优化。

webpack(当前版本,4.x)要求如果想要摇树优化,必须用es6的modules写法。而且注意拿给webpack打包前不能先用Babel转,因为这其实是会让es6的import/export语法变为cjs的语法,或者在presets中写清"modules" false:。同时需要在package.json文件中写清sideEffects。

可以在package.json 加一个 module 的字段来指向 es module规范的文件,main -> CommonJs,那么module - es module。webpack与rollup都支持这个字段。

CommonJs的 this 和 ES6 Module的 this

es6的module默认就是严格模式,因此会得到如下结果:

<script type="module">
  function logThis() {
    console.log(this)
  }
  logThis()  // 结果为undefined。
script>

node module中的最外层代码中,this等于module.exports。所以如果直接打印console.log(this),出来的是{}。如果在箭头函数中打印this,结果也是如此。

如果在function函数中使用this,其值决定于这个函数是怎么被执行的。在非严格模式下,直接执行函数,this等于global对象。严格模式下等于undefined。

在浏览器中也是同理。箭头函数和直接console this,结果都是window。如果在function中使用this,非严格模式下,在全局直接执行函数,this等于window,严格模式下是undefined。

stackoverflow上的这篇文章:this behaves differently in nodejs and browser下的第一个回答很好地解释了为什么。大意为,浏览器与nodejs不同之处在于,浏览器中,所有script都在window下加载,而nodejs则每个script文件都是在它自己的闭包下(一个module一个module)执行。Nodejs会把js文件中的this包装在一个匿名函数中,为每个文件(file/module)创建它自己的执行上下文。this处于module scope 而不是 global scope

而如果没有在调用函数时给定特定的上下文,函数中的this默认会指向全局对象。nodejs中是Global,浏览器中就是window。严格模式下,均为undefined。

umd通用

如果打包工具里指定了打出umd的包,那么一般可以见到这段代码:

(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined'? module.exports = factory() :
  typeof define  === 'function' && define.amd? define(factory) : (global.libName = factory())
})(this, (function() { 'use strict'; }))

这段代码的作用就是判断环境,以兼容各种模块加载方式。

你可能感兴趣的:(前端/Javascript,前端/打包压缩/webpack)