CommonJs和ES6模块

一、CommonJs

CommonJS中的导入使用require导入模块时,有下面两种情况(导出:exports和module.exports):

1.require的模块是第一次被加载.这时会首先执行该模块,然后导出内容
2.require的模块曾被加载过.这时该模块的代码不会再次执行,而是直接导出上次执行后的结果

//exports.js
console.log('cal.js')
module.exports = {
 name: '我是乔峰',
 add: function(a, b) {
   return a + b
 }
}
//import.js
// 第一次require
const add = require('./export').add
console.log(add(1, 2)) // cal.js 3
// 第二次require
const name = require('./export').name
console.log(name)// 我是乔峰

module.exports和exports的区别(导入:require):

1.exports = module.exports = {};
2.exports是module.exports的一个引用
3.require引用模块后,返回给调用者的是module.exports而不是exports
4.exports.xxx相当于在导出对象上挂属性
5.exports = xxx相当于给exports对象重新赋值(改变了exports的指向,使其指向其他对象),调用模块不能访问exports对象及其属性(所以exports = {a:xxx}或者exports = xxx得到的数据都是{})
6.如果此模块是一个类,就应该直接赋值module.exports,这样调用者就是一个类构造器,可以直接new实例

总结:exports会默认设置为module.exports的快捷方式,可以往里面添加属性( exports.test ),但是不可以修改它的指向,修改了他的指向,他就和普通的对象没有啥差别,因为在common.js里模块对外输出永远是module.exports,如果exports改变了指向之后,就会不在生效。module.exports的优先级会高于exports,module.exports中已经定义好的属性,exports修改不会生效

//export.js
module.exports = {
    name:'11',
    age:18,
    sex:'女'
};
exports.age = 22;

//import.js
let data = require("./export");
console.log("data",data);//{name:'11',age:18,sex:'女'}

require:

1.有时我们加载一个模块,不需要获取其导出的内容,只是想要通过执行它而产生某种作用,比如把它的接口挂载到全局对象上,此时直接使用require即可

require('./task.js')

2.require可以接收表达式,可以动态加载指定的模块

const moduleNames = ['foo.js', 'bar.js']
moduleNames.forEach(name => {
  require('./' + name)
})

博客地址:https://blog.51cto.com/u_11871779/2526416

二、.EsModule

导出:单个导出(export)和默认导出(export default):

1.单个导出在导入时不像CommonJs一样直接把值全部导入进来了,Es Module中可以导入我想要的值。那么默认导出就是全部直接导入进来

// export.js

// 导出变量
export const age = 24
// 导出函数也可以
export function fn() {}
export const test = () => {}
// 如果有多个的话
const name = "蛙人"
const sex = "male"
export { name, sex }

// import.js

import { name,age,fn,test,sex } from "./export.js";
console.log('导入的值',name,age,fn,test,sex);// 蛙人 24 [Function: fn] [Function: test] male

2.可以使用export和export default同时使用并且互不影响,只需要在导入时地方注意,如果文件里有混合导入,则必须先导入默认导出的,在导入单个导入的值。

导入

1.Es Module使用的是import语法进行导入。如果要单个导入则必须使用花括号{}

// export.js
export const name = "蛙人"
export const age = 24

// import.js
import { name, age } from './index.js'
console.log(name, age) // "蛙人" 24
// 如果里面全是单个导出,我们就想全部直接导入则可以这样写
import * as all from './index.js'
console.log(all) // {name: "蛙人", age: 24}

2.混合导入,则该文件内用到混合导入,import语句必须先是默认导出,后面再是单个导出,顺序一定要正确否则报错。
3.用export default导出的值,可以任意起别名(它本身没名字)

第一种:
// export.js
export default {
    msg: "蛙人"
}

//import.js
import data from './export.js'
console.log('导入的值',data);// { msg: '蛙人' }
第二种:
// export.js
let a = 123
export default a

// import.js
import c from './export.js'
console.log('导入的值',c); // 123
或者
import {default as all} from './export.js'
console.log('导入的值',all); // 123

4.export导出的值是值的引用,并且内部有映射关系,这是export关键字的作用。而且导入的值,不能进行修改也就是只读状态。

// export.js
export let num = 0;
export function add() {
    ++ num
}

//import.js
import {num,add} from './export.js'
console.log('add前的num',num);//0
add();
console.log('add后的num',num);//1
num = 10 // 报错

注意!!require导入的文件可以不加.js或.ts后缀,但是import导入必须要加!!

三、CommonJs和Es6模块的区别

  • CommonJs:
    • 对于基本数据类型,属于复制。即会被模块缓存。同时,在另一个模块可以对该模块输出的变量重新赋值。
    • 对于复杂数据类型,属于浅拷贝。由于两个模块引用的对象指向同一个内存空间,因此对该模块的值做修改时会影响另一个模块。
    • 当使用require命令加载某个模块时,就会运行整个模块的代码。
    • 当使用require命令加载同一个模块时,不会再执行该模块,而是取到缓存之中的值。也就是说,CommonJS模块无论加载多少次,都只会在第一次加载时运行一次,以后再加载,就返回第一次运行的结果,除非手动清除系统缓存。
    • 循环加载时,属于加载时执行。即脚本代码在require的时候,就会全部执行。一旦出现某个模块被"循环加载",就只输出已经执行的部分,还未执行的部分不会输出。
  • Es6模块
    • ES6模块中的值属于【动态只读引用】。
    • 对于只读来说,即不允许修改引入变量的值,import的变量是只读的,不论是基本数据类型还是复杂数据类型。当模块遇到import命令时,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。
    • 对于动态来说,原始值发生变化,import加载的值也会发生变化。不论是基本数据类型还是复杂数据类型。
    • 循环加载时,ES6模块是动态引用。只要两个模块之间存在某个引用,代码就能够执行。
  • 两者的区别
    • CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
    • CommonJS 模块的require()是同步加载模块,ES6 模块的import命令是异步加载,有一个独立的模块依赖的解析阶段。
    • CommonJS是对模块的浅拷贝,ES6 Module是对模块的引入,即ES6 Module只存只读,不能改变其值,具体点就是指针指向不能变,类似const 。
    • import的接口是read-only(只读状态),不能修改其变量值。 即不能修改其变量的指针指向,但可以改变变量内部指针指向。可以对commonJS对重新赋值(改变指针指向),但是对ES6 Module赋值会编译报错。
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容