0


一篇文章说透require和import的区别

1. 介绍

require/exports 和 import/exoprt 属于两种不同的模块化规范. require/exports 遵循 CommonJS 模块规范, 而 import/exoprt 遵循 ES6 模块规范.

那么怎么理解模块化规范?

模块化规范: 即为javascript提供模块编写 模块依赖 模块运行的方案

CommonJS模块规范
  • 出现的时间在2010年左右, 属于是野生规范, 即 JavaScript 社区中的开发者自己草拟的规则,得到了大家的承认或者广泛的应用
  • nodejs 使用的就是 CommonJS 规范
ES6模块规范
  • 出现的时间是在2015年, 属于是名门正派, 是 TC39 制定的新的 ECMAScript 版本, 即ES6(2015)包含进来的

2. ES model 和 CommonJS model 使用(node环境)

2.1 CommonJS

// a.jslet a =1let b =1functionadd(a, b){return a + b
}// 导出1
module.exports ={
    a,
    b,
    add
}// 导出2// exports.a = a// exports.b = b// exports.add = add
// index.js// 导入let obj =require("./a")

console.log(obj);// { a: 1, b: 1, add: [Function: add] }
console.log(obj.a);// 1
console.log(obj.b);// 2
console.log(obj.add);// add: [Function: add]

2.2 ES6

注意: CommonJS 模块是 Node.js 专用的,与 ES6 模块不兼容. 如果想要在node环境下执行import/export, 需要采用xxx.mjs的后缀名

// a.mjs// 导出方式1exportconst aaa ='aaa'exportconst bbb ='bbb'exportconst ccc ='ccc'const str ='hello es module'// 导出方式2exportdefault  str
// index.mjs// 引入方式1import{ aaa , bbb, ccc }from"./a.mjs"
console.log(aaa);// 'aaa'
console.log(ccc);// 'bbb'
console.log(str);// 'ccc'// 引入方式2  对应导出方式2// import str from "./a.mjs"// console.log(str); // hello es module// 引入方式3   1 + 2结合// import str, { aaa , bbb, ccc } from "./a.mjs"// console.log(str);// console.log(aaa);// console.log(ccc);// console.log(str);// 引入方式4  as别名// import { aaa as ddd } from "./a.mjs"// console.log(ddd); // 'aaa'// 引入方式5  * as// import * as obj from "./a.mjs"// console.log(obj); // { aaa: 'aaa', bbb: 'bbb', ccc: 'ccc', default: 'hello es module' }

3. ES model 和 CommonJS model 区别

3-1. ES6 模块输出的是值的引用,CommonJS 模块输出的是值的拷贝。

3-1-1. ES6 ⇒ 值的引用

解释一下, CommonJS 是值的拷贝(浅拷贝),怎么理解, 可以理解为 ⇒ 输出一个值, 如果模块内部这个值改变,输出的值不会受影响, 看下面代码

// a.jsvar num =1functionadd(){
    num++}

module.exports ={
  num,
  add,}
// index.js// 导入let obj =require("./a")

console.log(obj.num);// 1   输出一个值
obj.add()//     模块内部这个值改变
console.log(obj.num);// 1   输出的值不受影响

可以看到当我执行obj.add()之后,在打印obj.num,发现这个值并没有改变. 为什么呢? 这是因为mod.counter是一个原始类型的值,会被缓存。除非写成一个函数,才能得到内部变动后的值。

3-1-2. CommonJS ⇒ 值的拷贝

ES module 运行机制和 Commonjs 不一样, 预编译的时候如果读到了 import, 那么就会生成一个只读的引用, 再根据这个引用去对应模块取值. 意思就是原始值变了, import加载的值也会跟这边, 因此,ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块

// a.mjsexportvar num =1exportfunctionadd(){
    num++}
// index.mjsimport{ num , add }from"./a.mjs"

console.log(num);// 1  输出一个值add()//    模块内部这个值改变
console.log(num);// 2  输出的值受影响

3-2. CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。

因为 CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成

// commonjslet _fs =require('fs')let stat = _fs.stat
let exists = _fs.exists
let readfile = _fs.readfile
// 上面需要等待整体加载玩fs模块,生成一个_fs模块,然后再从对象上读取三个方法.这种加载称为运行时加载
// esimport{ stat, exists, readfile }from'fs'// 上面直接冲fs模块中加载3个方法,其他方法不加载,这种加载称为编译时加载. 即es6可以在编译的时候就完成模块加载

3-3. CommonJS 模块的require()是同步加载模块,ES6 模块的import命令是异步加载,有一个独立的模块依赖的解析阶段。

  • 同步: 会阻塞后续代码
  • 异步: 不会阻塞后续代码

commonjs

// index.jsconstA=require('./a')
console.log('index.js执行');// a.js
console.log('a.js执行')constfoo=()=>{
  console.log(require('./b').c);}foo()

module.exports ={
  foo
}// b.js
console.log('b.js执行');const c =3

module.exports ={
  c
}//执行node index.js// a.js执行// b.js执行// 3// index.js执行

es

// index.mjsimport{ foo }from"./a.mjs"
console.log('index.js执行');// a.mjs
console.log('a.mjs执行')exportconstfoo=()=>{import('./b.mjs').then(({c})=>{
    console.log(c);})}foo()// b.mjs
console.log('b.mjs运行');exportconst c =3//执行node index.mjs// a.mjs执行// index.js执行// b.mjs运行// 3

可以看出来: import()是异步加载的,因为index.js在前面打印了,而不是在最后打印,代表他没有被阻塞

3-4. 变量提升

es6
// a.mjs
console.log('我是a.mjs内容');import{ num }from'./b.mjs'
console.log(num);// b.mjs
console.log('我是b.mjs内容');exportlet num =100// 执行 node a.mjs// 我是b.mjs内容// 我是a.mjs内容// 100
commonjs
// a.js
console.log('我是a.js内容');let obj =require('./b')
console.log(obj.num);// b.js
console.log('我是b.js内容');let num =100
module.exports ={
  num
}// 执行 node a.js// 我是a.js内容// 我是b.js内容// 100

可以看到es6现打印了b.js内容, 而connonjs现打印了a.js的内容, 在es6模块中,当预解析a.js时候,发现import,就会去加载b.js. 整个流程就是预编译a.js ⇒ 发现import ⇒ 预解析b.js ⇒ 执行b.js ⇒ 执行a.js

4. 总结

1. ES module是值的引用 CommonJS module是值的拷贝

2. CommonJS 模块是运行时加载,ES6 模块是编译时加载。

3. CommonJS 模块是同步加载,ES6 模块是异步加载,

5. 结语

如果这篇文章帮到了你,欢迎点赞👍和关注⭐️。
文章如有错误之处,希望在评论区指正🙏🙏。


本文转载自: https://blog.csdn.net/weixin_46391646/article/details/124705188
版权归原作者 潘潘同学 所有, 如有侵权,请联系我们删除。

“一篇文章说透require和import的区别”的评论:

还没有评论