CommonJs和ES Module

Posted 登楼痕

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CommonJs和ES Module相关的知识,希望对你有一定的参考价值。

commonJs实现原理:

编译过程中将导出的代码js进行首尾包装进一个函数内:

function wrapper (script) {
    return '(function (exports, require, module, __filename, __dirname) {' +
        script +
     '\\n})'
}

模块加载的时候通过runInThisContext执行modulefunction,传入require那些参数。

在使用require引入的时候,require("xxxx")可以写为核心模块例如fs、path那些,可以是相对or绝对路径,也可以是第三方模块。

1、核心模块:加载优先级仅次于缓存加载,因为核心模块已经被编译成二进制文件所以加载速度很快;

2、文件路径:会将路径转换为真实路径,作为索引,缓存起来;

3、自定义模块:会先逐级寻找node_modules直到根目录,并且会找package.json下main指向的文件,若没有则去node环境寻找index.js等。

require引入的文件,采用深度优先遍历按父-子-父顺序执行,在引入的时候会避免重复加载循环引入,因为首次加载的文件的module会被缓存到Module对象上,当执行到后面代码如果其他文件又引入了这个文件,则会直接读取Module上的缓存而不会再次执行。

exports和module.exports这两个持有相同的引用

exports使用的时候必须exports.xxx=xxx; exports.zzz=zzz,不能直接用对象进行覆盖,比如exports={xx:xx, yy:yy},因为exports是作为形参传入的,在js内部修改没有意义,外部的exports不会改变,所以只能用exports.xxx这样增加属性。

对于module.exports其实本质就是exports,二者指向同一地址,类似于let a = new Object(); let b=a; 所以如果exports直接被覆盖了,那么js内部exports地址的复制品的引用也会改变了,对外部的exports没有影响。但如果是exports.xxx改变参数,就是改变的地址指向存储在栈内的值。

 所以不要在一个js文件中exports和module.exports同时使用,避免引起混乱。

提一嘴:

CommonJS同步加载并执行模块文件,对于服务器而言读取硬盘速度快,但是浏览器读取时的等待时间取决于网速等等因素,所以需要异步加载模块,因此有了AMD,也就是Asynchronous Module Definition。接受俩参数:require([module],callback())。像require.js、curl.js实现了AMD规范。

 

ES Module

es6之后js真正有了自己的模块化规范,export到处,import引入。

export导出有两种方式:

1、命名式导出:export {a,b},import {a,b} from "...", 其中a,b这些名字要对应,也可以用as重命名

2、默认导出:export default anything,import anyName from "..",这样anyName可以是自定义名称。

特性:

1、静态语法:ES6 Module的引入和导出是静态的,import会自动提升到代码顶层,export不能放到块级作用于或者条件语句中,比如说放在函数里写一句export或者if(export)这种。另外import的导入名称不能是字符串或者表达式。

2、ES6 Module是提前加载并执行模块文件,预处理阶段分析依赖,执行阶段进行执行,执行顺序是由子到父。

3、导出绑定:import执行在严格模式下,由import引入的变量是read-only,无法被赋值,并且是与原变量绑定引用的,也就是引用传递(无论是否为基础类型),可以用过同时导出一个方法来修改。

import()返回的是一个Promise,所以可以用.then进行动态引入。

以上是关于CommonJs和ES Module的主要内容,如果未能解决你的问题,请参考以下文章

CommonJs和ES Module

CommonJs和ES6 module的异同和使用整理(定期整理)

ES6-Module与CommonJs

commonjs 与 ES6 模块化

amd cmd commonjs 模块规范 和 es6 的 module 语法

前端模块化:CommonJS,AMD,CMD,ES6