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

这篇具有很好参考价值的文章主要介绍了一篇文章说透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.js
let a = 1
let b = 1
function add(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

// 导出方式1
export const aaa = 'aaa'
export const bbb = 'bbb'
export const ccc = 'ccc'

const str = 'hello es module'
// 导出方式2
export default  str
// index.mjs

// 引入方式1
import { 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.js
var num = 1
function add() {
	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.mjs
export var num = 1
export function add() {
	num++
}
// index.mjs
import { num , add } from "./a.mjs"

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

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

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

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

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

  • 同步: 会阻塞后续代码
  • 异步: 不会阻塞后续代码
commonjs
// index.js
const A = require('./a')
console.log('index.js执行');

// a.js
console.log('a.js执行')
const foo = () => {
  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.mjs
import { foo } from "./a.mjs"
console.log('index.js执行');

// a.mjs
console.log('a.mjs执行')
export const foo = () => {
  import('./b.mjs').then(({c}) => {
    console.log(c);
  })
}

foo()

// b.mjs
console.log('b.mjs运行');

export const 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内容');
export let 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://www.toymoban.com/news/detail-444760.html

到了这里,关于一篇文章说透require和import的区别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 一篇文章搞懂 push_back 和 emplace_back 的区别

    本来以为自己对 push_back 和 emplace_back 的理解还行,直到我室友伦伦问了一个关于 push_back 和 emplace_back 的问题。死去的 modern effective c++ 记忆又开始攻击我…因此,我痛定思痛,在阅读了大量文献之后写下本文。 (全篇 1200 字阅读大约需要 8 分钟) 撰写本文出于两点原因: 该

    2024年02月08日
    浏览(25)
  • 【C语言】一篇文章深入解析联合体和枚举且和结构体的区别

    联合体( union )是允许一个变量通过不同的接口访问内存的一种数据类型,表示一个变量可以存储不同类型的值,而枚举是使用 enum 定义一组相关且互斥的整形常量集合。本章阿森将和你学习联合体类型的声明,特点,有关大小的计算,还有枚举类型的声明,优点和使

    2024年02月03日
    浏览(32)
  • 一篇文章学会高级IO

    IO是数据在传输时的一种动作描述,分为输入数据(I)和输出数据(O)两种动作。和一般而言,IO都需要维护一个收发数据的缓冲区,例如read、recv函数和write、send函数,它们的数据缓冲区都是由系统帮助创建的。对于C语言中常用到的scanf函数和printf函数,同样不需要用户自

    2024年02月05日
    浏览(57)
  • 一篇文章理解虚拟滚动原理

    首先提到一个现象,前端的性能瓶颈那就是页面的卡顿,当然这种页面的卡顿包含了多种原因。例如HTTP请求过多导致数据加载国漫,下载的静态文件非常大导致页面加载时间很长,js中一些算法响应的时间过长等。很多前端工程师都花费很多的精力在dom渲染上来优化页面加载

    2024年02月05日
    浏览(27)
  • 一篇文章玩透awk

    awk有很多种版本,例如nawk、gawk。gawk是GNU awk,它的功能很丰富。 本教程采用的是gawk 4.2.0版本,4.2.0版本的gawk是一个比较大的改版,新支持的一些特性非常好用,而在低于4.2.0版本时这些语法可能会报错。所以,请先安装4.2.0版本或更高版本的gawk。 查看awk版本 这里以安装ga

    2024年02月06日
    浏览(31)
  • 一篇文章完成Hbase入门

    HBase是一种分布式、可扩展、支持海量数据存储的NoSQL数据库。 1、数据模型结构 逻辑上,HBase的数据模型同关系型数据库很类似,数据存储在一张表中,有行有列。但从HBase的底层物理存储结构(K-V)来看,HBase更像是一个multi-dimensional map(多维地图) HBase逻辑结构 2、物理存

    2024年01月16日
    浏览(37)
  • 七大 排序算法(一篇文章梳理)

    排序算法是计算机科学中不可或缺的一部分,它们在数据处理、数据库管理、搜索引擎、数据分析等多个领域都有广泛的应用。排序算法的主要任务是将一组数据元素按照某种特定的顺序(如升序或降序)进行排列。本文将对一些常见的排序算法进行详细的介绍和分析,包括

    2024年03月08日
    浏览(41)
  • ai写作软件怎么写文章?这篇文章介绍三个好方法

    在人工智能技术的迅速发展下,ai写作成为创作领域的一项炙手可热的新技术。随着越来越多的创作者开始借助ai写作工具,ai写作逐渐引起了广泛的关注。ai写作是指利用人工智能技术和自然语言处理算法,为创作者提供文章的初版。不过有很多小伙伴对这一项技术还不太了

    2024年02月11日
    浏览(29)
  • 【八大排序】一篇文章搞定所有排序

    1.1排序的概念 排序:所谓排序,就是使一串记录,按照其中的某个或某些的大小,递增或递减的排列起来的操作。 稳定性:假定在待排序的记录序列中,存在多个具有相同的的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中, r[i]=r[j],且r[i

    2024年04月09日
    浏览(69)
  • 一篇文章吃透背包问题!!!【动态规划】

    简单来说就是:一个小偷背了一个背包潜进了金店,包就那么大,他如果保证他背出来所有物品加起来的 价值最大 。 规范描述就是:有一个容量为 W 的背包,要用这个背包装下物品的 价值最大 ,这些物品有两个属性:体积 w 和价值 v 。 最常见的背包问题有 0-1背包 , 完全

    2024年02月05日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包