2023年才开始学nodejs,晚了吗?裂胃!

173 阅读5分钟

我觉得在开始真正学习nodejs之前要能回答这几个问题

我觉得开始学任何一个新的技能之前都要回答是什么的问题,正好我最近在学习nodejs,在这里记录我的学习过程,

本文纯自学内容,如有错误请大家指出!

1.什么是nodejs??

  1. nodejs 是JavaScript的后端运行环境,而我们熟悉的浏览器则是JavaScript的前端运行环境;
  2. nodejs 是基于chorme V8引擎解析的;
  3. 由于nodejs是JavaScript的后端运行环境,所以nodejs中没有对应操作DOM/BOM的api;

2.什么是运行环境??

所谓运行环境就是能将编程语言编译成机器能够识别的二进制代码,通过计算机的运算最终输出我们想要的结果以达到我们使用该语言的目的。

很多语言都有对应的运行环境,比如:

c/c++ 语言通过gcc/g++ 运行环境编译 运行指令: gcc test.c test.cpp

python 语言通过 python 运行环境编译 运行指令: python test.py

javascript 语言通过node 运行环境编译 运行指令: node test.js

3.为什么要有模块化??

了解什么是nodejs,并且知道了nodejs是JavaScript语言的运行环境之后,进一步需要了解nodejs最基础的模块化知识,那么为什么需要了解模块化?

  1. 方便维护

  2. 不同模块相互独立,即使定义相同的变量或者函数也不会互相影响

  3. 公共模块抽离,易于逻辑复用、维护等

进入正题后》CommonJS规范和ESModule规范

CommonJS

CommonJS规范

最开始Node.js是遵循了 CommonJS 模块化规范,CommonJS 规定了模块的特性和各模块之间如何相互依赖。

CommonJS规范核心概念:

① 在每个模块内部,规定了使用module变量代表/描述当前模块

② module 变量是一个对象,它的 exports 属性(即 module.exports )是对外的接口

在一个小的测试中分别打印了 console.log(module) console.log(exports) 可以看到module是一个对象,他的身上有很多属性都是在描述当前模块,比如:

path: [当前文件的绝对路径]

exports:[表示当前模块需要导出到外部使用的变量或者对象]

filename:[文件完整路径]

children:[子模块,即当前模块是否使用require引入了其他模块]

image.png

CommonJS的三种导出写法

这里只要理解module身上的exports属性是个对象就能理解为什么有这些写法了,其实就是给对象赋值的几种写法而已;

function test(){
    console.log('test-aaa')
}
function upper(str){
    return str.substring(0,1).toUpperCase()+str.substring(1)
}

//1. 只导出一个变量时;
// module.exports = test

//2. 导出多个变量的时候;
// module.exports = {
//     test:test,
//     upper:upper,
// }

//3. 给exports对象赋值的方式;
exports.test = test;
exports.upper = upper

//当然我们最常用的还是第二种;

ESModule

随着ECMAScript的发展, nodejs迫于压力也开始支持es6规范,且es6规范前后端通用;

基本用法:

① 需要在package.json 中 添加 "type": "module", 默认不写为 "type": "commonjs"

② import 模块的时候需要写完整名字+后缀

esmodule的两种导出方式:命名导出和默认导出

默认导出和命名导出是可以同时出现在一个文件中的

  默认导出的两种方式

1. export default modulea  
//对应这种写法引入一个模块
import modulea from './modulea.js'

2. 分别暴露
 export default
 {
    modulea,
    moduleb
 }
 //解构的方式引入
 import { modulea } from './modulea.js'
 
命名导出 
export const foo = 'foo'
export default modulea  

默认导出和命名导出是可以同时出现在一个文件中的~

注意: ESModule和CommonJS两种规范不可混用!

ESModule和CommonJS的区别:

想要了解ESModule和CommonJS两者的区别,就需要大致了解一下模块化的发展过程,包括被废弃的AMD和UMD规范, 这里简单说下我的理解,CommonJS模块化规范的出现主要是为了解决js在nodejs环境运行时存在的问题,而在浏览器环境运行js有衍生出了AMD规范,nodejs和浏览器运行环境最主要的区别是加载模块的依赖时,在浏览器端往往通过发送网络请求获取,但这往往需要时间;包括后来的UMD规范都是为了兼容浏览器和nodejs这两种js运行环境出现的。 而ESModule在很多地方都借鉴了CommonJS和AMD的思想,做到真正意义上的前后端一致的通用性模块化规范!

所以第一条区别就是

1.CommonJS是同步加载模块而ESModule是异步加载模块的;

2.ESModule中import语句被提升到模块顶部(但推荐写在顶部),require方法不会;

3.CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用; zhuanlan.zhihu.com/p/524346119 [膜拜]

4.CommonJS和ES6 模块加载依赖的方式不同,ES6 使用静态加载,即在编译时就处理模块依赖关系;而 CommonJS 使用动态加载,即在运行时处理模块依赖关系。

其他:摘自官网nodejs.org/api/esm.htm…

  1. 大多数情况下,ES Module import 可以用来加载CommonJS 模块
  2. 如果有需要,require方法可以在ES Module中可以使用module.createRequire()代替
  3. __filename和__dirname 这两个变量在ESMoudle中不生效
  4. 在ESMoudle中可以使用import.meta.url代替

本小节就探讨到这里啦~

参考:

红宝书第26章

官网:nodejs.org/api/esm.htm…

其他博客:zhuanlan.zhihu.com/p/524346119

课程:www.bilibili.com/video/BV1rA…

希望和大家共同学习!

有什么理解不到位的,欢迎互相讨论学习,前端程序猿一枚

创作不易 如果感觉有收获,就请给我点个赞吧~