es6模块化导入导出与commonjs模块化(nodejs导入导出)详解——导入import

博主的桌面工具软件已经正式开发,获取方式:

  • 可以关注我的小程序【中二少年工具箱】获取。(若小程序更新有延迟,或关注小程序后续功能,可先收藏小程序)

  • 通过下载链接

  • 百度网盘: 链接:pan.baidu.com/s/15zDnSoEz... 提取码:1234 复制这段内容后打开百度网盘手机App,操作更方便哦

具体已实现功能,参考文章中二少年工具箱简介


@TOC


前言

前面文章已经讲解es6模块化和commonjs模块化的导出语法,博主一贯作风都是只讲干货,不抄文档,前端同学去看看,绝对会有感触。

当然讲干货意味着加入了自己的理解,如果有失偏颇,还请各位大佬在不吝指教的同时,又能保持风度。

不水文的原创真的是太难了,感觉文章不错的同学积极点赞收藏和私信加群,不要矜持,很多技能边界,聊着聊着就拓展了。


一、commonjs模块化的导入

下表是上篇文章做过的对比:

导出语法 导入语法
commonjs模块化 1. module.exports=xxx 2.exports.变量名=xxx const xxx=require()
es6模块化 1.export default xxx 2. export xxx 1.import {xxx} from 2.import xxx from 3.import * as xxx from

为什么我这里对于commonjs模块化的导入语法,只写了一种?那是因为我们初学只需要关注这一种语法,其它的都是变种。

类似于数学中某一章节的定理可能只有一个,但是推理可以有很多个。理解了定理,推理不需要死记硬背。

写个简单例子:

c 复制代码
const test=require('test.js')

这句话的意思是,在test.js中导出了一个对象,我们在这里得到这个对象,并赋值给变量test。上一章节我们详细讲过,commonjs导入导出是运行时进行,得到的是真正的对象,即exports。

不论以哪种形式导出对象,得到的都是这一个exports对象,所以导入时,自然也就只有一种语法。

那么我们为什么常见下面的写法:

c 复制代码
const {a,b}=require('test.js')

这不过是一种变种写法,将解构语法和导入语法合二为一。其实它等价于两句话:

c 复制代码
const test=require('test.js')
const {a,b}=test

而对应的导入语法也就有两种:

c 复制代码
module.exports={
a:'1',
b:'2'
}
//或者
exports.a='1'
exports.b='2'

这就显而易见了,导出的永远是exports对象,对象里可以有其它属性,得到的永远都是test变量,变量可以直接解构出属性a、b。

在commonjs导出中,module.exports优先级高于exports,但是两者导出结果一样。

二、es6模块化导入

es6的模块化导入就不同于commonjs导入那么省事了。它不同的写法并不是变种,而是针对不同的场景。

  1. import {xxx} from
c 复制代码
import {xxx} from 'test.js'

这种写法是从test.js中导出命名导出的变量/函数,也就是说这种写法就对应着

c 复制代码
const xxx=...
export xxx

//或者合并两句
export const xxx=...
  1. import xxx from
c 复制代码
import xxx from 'test.js'

这种写法是导入test.js中的默认导出模块,也就是对应着

c 复制代码
export default xxx 

如果你认真看过上一篇文章,那么应该理解上面两句代码中的xxx含义不同,导出语法导出的变量是default,这句计算机语言如果翻译成人话,更清晰的表述应该是类似:导出一个变量default,并为它赋值为xxx。而导入中的xxx则是指向导出的default,和导出中的xxx没有直接关系,所以两种并不用同名。也就是上面两句代码等价于:

c 复制代码
import test from 'test.js'

export default xxx
  1. import * as xxx from

这是一种整体导入的方式,就是不管导出了哪些变量,我都导入并且把它赋值给xxx,然后可以通过==xxx.变量名== 的方式获取其中的变量。

三、运行时与静态分析时

仔细对比两种导入语法,我们可以发现require导入更像是一个函数,而import xxx from则更像一种固定的语法。

require()确实是一个内置的函数,与console.log()、alert()、parseInt()等等函数并没有什么区别。所以require导入模块是发生在运行时,也就是代码运行到这了,就会调用这个函数。

而import from并不是函数,它是发生在静态分析时,也就是编译时。它的作用是在这个位置插了个标记,告诉node,你以后编译代码,操作文件时,记得把from后面那个文件里的xxx函数给写到这里。

也就是说import引入的模块生效时,是在项目代码真正运行的阶段,但是模块早在代码运行之前,就已经被node自动写到了这里。

import虽然和普通函数写在一起,但是它们并不是一类。import真正生效的时机是在代码运行之前的编译过程,而其他普通函数生效的时机就是代码运行的时候。

所以我们这样写就会报错:

c 复制代码
for(let i=0;i<2;i++){
import xxx from 'test.js'
}
if(1==1){
import xxx from 'test.js'
}

因为不管是for还是if,都是代码运行时的语法,而import是编译时需要查找的标记,nodejs在查找组合各个文件时,它知道什么是if和for吗,不知道!在node眼里,所有的一切都是文本字符而已,它的任务也不是去运行什么,而是找到相应的export,把它写入到import的位置而已。

五、总结

我写的两篇导入导出,只是自己的一些粗浅理解,想要了解模块化的全貌,还是要学习官方文档。这里强烈推荐阮一峰大神的es6入门教程作为参考手册。

相关推荐
ᥬ 小月亮8 分钟前
Js前端模块化规范及其产品
开发语言·前端·javascript
码小瑞23 分钟前
某些iphone手机录音获取流stream延迟问题 以及 录音一次第二次不录音问题
前端·javascript·vue.js
weixin_18925 分钟前
‌Vite和Webpack区别 及 优劣势
前端·webpack·vue·vite
半吊子伯爵26 分钟前
开发过程优化·自定义鼠标右键菜单
前端·javascript·自定义鼠标右键菜单
xcLeigh29 分钟前
HTML5实现好看的喜庆圣诞节网站源码
前端·html·html5
Tirzano1 小时前
vue3 ts 简单动态表单 和表格
前端·javascript·vue.js
杰~JIE1 小时前
前端工程化概述(初版)
前端·自动化·工程化·前端工程化·sop
程序员_三木1 小时前
使用 Three.js 创建圣诞树场景
开发语言·前端·javascript·ecmascript·three
赵大仁1 小时前
深入理解 Vue 3 中的具名插槽
前端·javascript·vue.js·react.js·前端框架·ecmascript·html5
一雨方知深秋1 小时前
v-bind 操作 class(对象,数组),v-bind 操作 style
前端·css·vue.js·html·style·class·v-bind