文章目录
- 名词解释
- 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'; }))
这段代码的作用就是判断环境,以兼容各种模块加载方式。