NodeJs(一):初识nodejs、模块化、CommonJS、ESModule等

目录

(一)Nodejs简介

1.nodejs是什么

2.nodejs架构

3.nodejs的应用场景

(二)准备工作

1.安装nodejs

2.nodejs版本管理工具

(三)nodejs的使用

1.node的输入

2.node的输出

3.其他的console方法

(四)全局对象

1.常见的全局对象

2.特殊的全局对象

3.global和window的区别 

(五)模块化***

1.什么是模块化

2.CommonJS

(1)CommonJS的广泛使用

(2)CommonJS在Node的使用

(3)CommonJS在Node实现的本质

(4)module.exports的本质

(5)require()查找模块的细节

(6)Node模块的加载过程

多次引入的模块加载

循环引入的模块加载顺序

3.ES Module

(1)es module的导入和导出

(2)导出(暴露)的三种方法 

(3)导入的三种方法

(4)import函数

import() 

import.meta


(一)Nodejs简介

1.nodejs是什么

nodejs是基于v8 JavaScript引擎的运行时环境

node基于v8引擎来执行js文件,但不仅仅只有v8引擎,也有额外的操作,如文件读写、网络IO、加密、压缩解压文件等操作

2.nodejs架构

node是用JS、C、C++语言编写的

编写的js代码会通过v8引擎,再经过nodejs的bindings,将任务放到Libuv的事件循环中

libuv:是使用C语言编写的库,提供了事件循环、文件系统读写、网络IO等内容

3.nodejs的应用场景

  1. 目前前端开发的库都是以node包的形式进行管理
  2. npm、yarn、pnpm工具成为前端开发使用最多的工具
  3. 使用nodejs作为服务器开发、中间件、代理服务器
  4. 大量项目需要借助nodejs完成前后端渲染的同构应用
  5. 为项目编写脚本工具

(二)准备工作

1.安装nodejs

在中文网里安装node.js: Node.Js中文网

LTS版本:更加稳定,不会轻易改变版本(项目开发推荐)

current版本:最新版本,拥有新特性,不太稳定 

2.nodejs版本管理工具

当需要使用到多个版本的node且来回切换时,可以使用版本工具进行快速安装和切换

n或nvm:适用于Mac系统

nvm-windows:适用于windows系统 GitHub - coreybutler/nvm-windows: A node.js version management utility for Windows. Ironically written in Go.

nvm-windows的基本使用:

在github里下载:Releases · coreybutler/nvm-windows · GitHub

nvm list ----列出nvm管理的node版本

nvm install xx版本 ----下载xx版本

nvm use xx版本 ----切换为xx版本

nvm current ----展示当前使用的node版本

(三)nodejs的使用

1.node的输入

在控制台运行js文件:node xxx 

输出:console.log()

2.node的输出

输入:node xxx 变量 变量...

输入的变量会存储在全局对象process的argv数组里,这个数组存储有node的路径和运行的js文件的路径,以及输入的变量

 

因此可以通过process.argv获取输入的变量值 

argv是什么?

是argument vector的缩写,指传入的具体的参数

3.其他的console方法

console.clear()清空控制台

console.trace()打印函数的调用栈

更多在文档中查看:Console | Node.js v19 API

(四)全局对象

这些对象在所有模块中都可用:Global objects | Node.js v19 API

1.常见的全局对象

global:全局对象

process:process对象提供有关当前Node.js进程的信息和控制 Process | Node.js v19 API

console:对控制台的简单调试

定时器函数:

setTimeout()

setInterval()

setImmediate():callback I/O事件之后的回调立即执行

setImmediate和setTimeout的执行顺序有区别,后续再x

process.nextTick():添加到下一次tick队列中

2.特殊的全局对象

以下变量可能看起来是全局的,但实际上不是。它们只存在于模块的作用域中

详情见:CommonJS modules | Node.js v19 API

__dirname:当前文件所在的目录结构

__filename:当前目录+文件名称

exports、module、require():在后面的模块化会着重讲到 

3.global和window的区别 

global对象是js运行时nodejs提供的全局对象,上文提到的process、console、定时器函数等都包含在global对象中;

window对象是浏览器的全局对象,里面也包含了console、定时器函数等;

但在浏览器里global相关的属性是不存在的,在node里window属性也是不存在的

因此使用全局属性globalThis可以解决该问题

globalThis - JavaScript | MDN

通过使用globalThis,你的代码将在 window 和非 window 上下文中工作,而无需编写额外的检查或测试。在大多数环境中,globalThis直接引用该环境的全局对象。但是,在浏览器中,内部使用代理来考虑iframe和跨 window 安全性。实际上,它并不会改变我们编写代码的方式。 

(五)模块化***

1.什么是模块化

  • 模块化开发是将程序划分为一个个小的模块结构,在各自的模块中编写自己的逻辑结构,有自己的作用域,不会造成全局变量的污染
  • 在这个模块结构中,可以将自己的变量、函数、对象等导出给其他模块使用,也可以引入其他模块的变量、函数、对象等为自己所用。

在早期js开发中,对于怎么样导入导出没有具体的规范,大家自发的建立起CommonJS、amd/cmd等模块开发规范,直到ES6的ESModule给出了官方的模块化规范 

2.CommonJS

(1)CommonJS的广泛使用

  • node是CommonJS在服务器端一个具有代表性的实现;
  • Browserify是CommonJS在浏览器的一个实现;
  • webpack打包工具具备对CommonJS的支持和转换

(2)CommonJS在Node的使用

nodejs的模块化是基于CommonJS的规范实现的

  • Node.js 应用由模块组成,每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。
  • 模块中包括CommonJS规范的核心变量:module、exports、require

模块的导出

exports、module.exports 

const name = 'csq'
function sayHello() {
    console.log('hello');
}

exports.name = name
exports.sayHello = sayHello

模块的导入

require()命令的基本功能是,读入并执行一个 js 文件,然后返回该模块的 exports 对象。如果没有发现指定模块,会报错。

const a = require('./a')
// 解构赋值
// const {name,sayHello} = require('./a')

console.log(a.name);
a.sayHello()

(3)CommonJS在Node实现的本质

require()通过引用赋值将另一模块的exports对象绑定在当前模块中

意思是:require获取到的对象和导出的对象指向同一个地址

在导入的模块中修改require获取到的对象,在导出模块的exports对象也会发生改变;反之,在导出模块的exports对象发生改变,那么在导入模块的require获取的对象也会发生改变。

在main.js中:
const a = require('./a')
console.log(a.name); // ‘csq’
// 2s后修改对象属性 对应导出的exports对象也会改变
setTimeout(() => {
    a.name = 'zkj'
}, 2000)

在a.js中:
const name = 'csq'
setTimeout(() => {
    console.log(exports.name); // ‘zkj’
}, 3000);

exports.name = name

(4)module.exports的本质

CommonJS中是没有module.exports的概念的,是依靠exports进行导出的。而在Node中为了实现模块的导出,使用的是Module类,每一个模块的实例也就是module,真正用于模块导出的是module.exports。因此exports只是指向了module.exports

如下图,require()导入的a和module.exports、exports都指向同一地址,因此对三者任意一个进行修改,其他的也都会改变 

在开发中,更加推荐的导出方法是:

// 推荐导出方法
module.exports = {
    name,
    sayHello
}

这种方法创建了一个新对象并将module.exports也指向了新的内存,exports对象也就没有了意义

因此,无论如何修改exports内的数据都不会影响到module.exports 

(5)require()查找模块的细节

情况一:require("内置模块名"):导入Node内置模块

如:path、http、fs等内置模块

情况二:require("路径"):导入自定义的模块

查找顺序:如"./xxx",会先按照以下顺序查找当前目录有无该文件:

        1.xxx

        2.xxx.js

        3.xxx.json

        4.xxx.node

当这些文件都没有后,再将xxx作为一个目录,自动补全index文件,查找目录后有无index文件,没有就会报错

情况三:require("外部模块"):当require内不是路径也不是内置模块时,会查找当前路径的node_modules文件夹,再在文件夹内寻找有无该模块;若当前路径没有node_modules文件夹,就向上一级文件夹依次继续寻找

例如require("axios") 需要通过node i axios下载后才能在node_modules内找到 

(6)Node模块的加载过程

多次引入的模块加载

第一次加载某个模块时,Node.js 会缓存该模块。以后再加载该模块,就直接从缓存取出该模块的exports属性返回

const a = require('./a')
// 第一次加载某个模块时,Node.js 会缓存该模块。
// 以后再加载该模块,就直接从缓存取出该模块的 module.exports 属性返回
a.name = 'zkj'
const b = require('./a')

console.log(b.name); // 'zkj'

由以上实例可证明,再次导入该模块,就不会再从该模块中重新加载了

原因:在module对象中有一个属性loaded默认为false,当导入后就会变为true,不会再被加载了

循环引入的模块加载顺序

当出现循环引入,如图

Node会按照图的深度优先算法进行遍历

即顺序:main ->aaa->ccc->ddd->eee->bbb 

3.ES Module

commonJS模块化适用于服务器端,而官方推出的ES Module是在浏览器端实现模块化的一个很好的方案

(1)es module的导入和导出

在浏览器中实现模块化,只需要在引入时 type=module即可

导入:import {xxx,yyy} from "xxx.js"

在main.js中:
// 在浏览器上使用模块化 导入时文件名后缀要写完整
import { name, sayHello } from "./a.js"
console.log(name); // ‘csq’
sayHello() // ‘hello’

注意:在浏览器使用esModule时要加上文件后缀js,否则查找不到对应文件

导出:export {xxx,yyy}

在a.js中:
let name = 'csq'
function sayHello() {
    console.log("hello");
}
export { name, sayHello }

注意:在浏览器使用ESModule必须开启一个服务端口打开对应html文件,否则会报错:不能通过本地下载js文件的方式解析,file协议前缀会被跨域策略阻止,必须使用http、https等协议前缀

在MDN上有解释:JavaScript 模块 - JavaScript | MDN

你需要注意本地测试——如果你通过本地加载 HTML 文件(比如一个 file:// 路径的文件),你将会遇到 CORS 错误,因为 JavaScript 模块安全性需要。你需要通过一个服务器来测试。 

(2)导出(暴露)的三种方法 

分别暴露

// 1.分别暴露
export let name = 'csq'
export function sayHello() {
    console.log("hello");
}

统一暴露

// 2.统一暴露
export { name, sayHello }

默认暴露

// 3.默认暴露 (只能暴露一个变量、方法或对象等)
export default {
    name:'csq',
    age:18
}

(3)导入的三种方法

// 1.导入方式1
import { name, sayHello } from "./a.js"

// 2.导入方式2 全部导入
import * as a from "./a.js"

// 3.默认暴露的导入
import sayHello from "./a.js";

注意:默认暴露的导入名字是自定义的,一般使用与导出相关的名字

(4)import函数

import和export命令只能在模块的顶层 

import命令会被 JavaScript 引擎静态分析,先于模块内的其他语句执行。若在if语句内写import语句,在编译时是不会被处理的,导致报语句错误,如下:

if(name){
    import { age } from "./b.js"; // 报错:导入声明只能在顶层使用
}
import() 

 ES2020 引入import()函数,支持动态加载模块

import("./xxx.js")函数返回一个promise对象

if (name) {
    import('./b.js').then(res => {
        console.log(res) // module对象
        console.log(res.age) // 18
    })
}

import()和require()一样都能实现动态加载模块,区别是:前者是异步加载,后者是同步加载

import.meta

开发者使用一个模块时,有时需要知道模板本身的一些信息(比如模块的路径)。ES2020 为 import 命令添加了一个元属性import.meta,返回当前模块的元信息

import.meta只能在模块内部使用,如果在模块外部使用会报错

console.log(import.meta); // 在b.js中

 

(5)ESModule解析过程**

https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/

构建:查找、下载并将所有文件解析为模块记录(Module record)

实例化:对模块记录进行实例化,分配内存空间,然后解析模块的导入和导出,将导出和导入都指向对应的内存地址

运行:运行代码,将实际的值填入对应的内存地址中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/209044.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

用友U8 ERP和面粉行业专版系统接口集成方案

面粉加工行业面临着数据管理和业务流程自动化的挑战。众诚ERP系统和用友U8系统的数据集成是解决这一挑战的关键。 解决方案 轻易云平台提供了一套完善的数据同步和集成解决方案,包括以下几个方面: 基础资料同步:包括物料、客户、供应商、仓…

matlab 路面裂缝检测识别系统设计GUI

1、内容简介 略 23-可以交流、咨询、答疑 2、内容说明 路面裂缝检测识别系统设计GUI 基于matlab的GUI设计路面裂缝检测识别系统 matlab、GUI、直方图、裂缝检测、二值化 3、仿真分析 4、参考论文 略 链接:https://pan.baidu.com/s/1AAJ_SlHseYpa5HAwMJlk…

​LeetCode解法汇总2661. 找出叠涂元素

目录链接: 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目: https://github.com/September26/java-algorithms 原题链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 描述: 给你一个下…

基于PHP的高中生物学习平台

有需要请加文章底部Q哦 可远程调试 基于PHP的高中生物学习平台 一 介绍 此高中生物学习平台基于原生PHP开发,数据库mysql。系统角色分为用户和管理员。(附带参考设计文档) 技术栈:phpmysqlphpstudyvscode 二 功能 学生 1 注册/登录/注销 2 个人中心 …

Unittest(1):unittest单元测试框架简介setup前置初始化和teardown后置操作

unittest单元测试框架简介 unittest是python内置的单元测试框架,具备编写用例、组 织用例、执行用例、功能,可以结合selenium进行UI自动化测 试,也可以结合appium、requests等模块做其它自动化测试 官方文档:https://docs.pytho…

CSS 多主题切换思路

前言 本篇仅提供多主题切换思路,示例简单且清晰。 实现 步骤一:多主题(颜色)定义 定义根伪类 :root,代码第 2 和 7 行。分别定义了默认和带参数的伪类;定义 CSS 变量,注意变量名需要以两个减号(--&…

如何选择适合长期投资的股票板块?

大家在学习炒股的过程中肯定没少听“板块”这个词,新手可能一脸懵逼,板块到底是啥意思?为什么会有这么多板块? 一、什么是股票板块?常见的板块分类有哪些? 板块理解起来其实很简单,它就是一种分…

API成批分配漏洞介绍与解决方案

一、API成批分配漏洞介绍 批量分配:在API的业务对象或数据结构中,通常存在多个属性,攻击者通过篡改属性值的方式,达到攻击目的。比如通过设置user.is_admin和user.is_manager的值提升用户权限等级;假设某API的默认接口…

从自动化、数字化到智能化,鸿蒙与制造业的双向奔赴

终端万物互联,商业竞争瞬息万变,制造企业面临着数字化转型与产品智能化升级的双重考验。鸿蒙操作系统以统一操作系统方案,可以为制造企业解决设备生态碎片化以及跨终端对接问题,提供安全性、流畅度、多屏协同等功能,实…

将本地项目推送到github

欢迎大家到我的博客浏览。将本地项目推送到github | YinKais Blog 本地项目上传至 GitHub<!--more--> 1、进入项目根目录&#xff0c;初始化本地仓库 git init 2、创建密钥&#xff1a;创建 .ssh 文件夹&#xff0c;并进入 .ssh 文件夹 mkdir .ssh cd .ssh/ 3、生成…

Robotframework自动化常见问题总结

Robotframework自动化新手常见问题总结 1. 经常有人问这个元素找不到&#xff0c;一般先排除这两个地方&#xff0c;再自己找找 A&#xff1a;是否等待了足够的时间让元素加载 (增加sleep xx, wait Until xxx) B: 仔细查查&#xff0c;这个元素是否进入到另一个frame了 (sel…

基于Intel Ai Analytics Toolkit 及边缘计算的溶氧预测水产养殖监测方案

基于AI的淡水养殖水质溯源、优化系统方案 前言一、关键需求及方案概述二、方案设计预测机制LSTM 模型基于intel AI 的时序水质分析模型与分类模型优化 三、实战分析1、方案简述2、数据分析预处理特征类型处理特征分布分析 3、特征构造4、特征选择过滤法重要性排序 5.构建LSTM模…

java游戏攻略资讯网站的设计与实现springboot+vue

游戏攻略网站分为管理员与用户两种角色。 管理员的功能包括登录&#xff0c;用户管理&#xff0c;游戏分类管理&#xff0c;游戏攻略管理&#xff0c;游戏资讯管理等。 登录功能&#xff1a;管理员需要登录进入系统后台。 用户管理&#xff1a;实现用户信息的查询&#xff0c;修…

TCP 重传、滑动窗口、流量控制、拥塞控制

1&#xff1a;重传机制 超时重传 快速重传 SACK 方法 Duplicate SACK 1&#xff1a;重传机制 超时重传&#xff1a;重传机制的其中一个方式&#xff0c;就是在发送数据时&#xff0c;设定一个定时器&#xff0c;当超过指定的时间后&#xff0c;没有收到对方的ACK确认应答报文…

vue3 中使用 sse 最佳实践,封装工具

工具 // 接受参数 export interface SSEChatParams {url: string,// sse 连接onmessage: (event: MessageEvent) > void,// 处理消息的函数onopen: () > void,// 建立连接触发的事件finallyHandler: () > void,// 相当于 try_finally 中的 finally 部分&#xff0c;不…

读书笔记-《数据结构与算法》-摘要1[数据结构]

文章目录 [数据结构]1. String - 字符串2. Linked List - 链表2.1 链表的基本操作2.1.1 反转链表单向链表双向链表 2.1.2 删除链表中的某个节点2.1.3 链表指针的鲁棒性2.1.4 快慢指针 3. Binary Tree - 二叉树3.1 树的遍历3.2 Binary Search Tree - 二叉查找树 4. Queue - 队列…

JDK21无法导入TimeUnit类

运行环境&#xff1a;windows11、IDEA2023.1.3、JDK21 问题描述&#xff1a;IDEA中无法导入java.util.concurrent.TimeUnit类。 以下截图是问题解决后的截图。有问题的时候未截图&#xff0c;说明一下&#xff0c;有问题的时候TimeUnit类是红色的&#xff0c;无法导入&#x…

申请开通QMT量化需要多少资金?免费开通!

最近量化交易在市场上大火&#xff0c;很多投资者想要参与进来。QMT量化软件是目前市场上一款比较常见并且强大的量化软件。那开通QMT量化交易软件需要多少资金&#xff1f; QMT量化交易软件是一种专门用于量化交易的工具&#xff0c;它能够帮助投资者通过程序化交易策略进行股…

布隆过滤器

目录 布隆过滤器的提出 布隆过滤器的概念 布隆过滤器的实现 布隆过滤器的插入 布隆过滤器的查找 布隆过滤器的删除 布隆过滤器的优点 布隆过滤器的缺点 布隆过滤器的使用场景 布隆过滤器的提出 在注册账号设置昵称的时候,为了保证每个用户的昵称唯一性,系统必须检测…

庆科EMW3080wifi模组烧录AT固件

本文记录庆科的EMW3080wifi模组烧写AT固件的过程&#xff1b; 参考文档&#xff1a;https://mxchip.yuque.com/zc9vym/tn0rwo/kgs4lx?singleDoc#NrlEB 以上链接为庆科方提供的文档&#xff0c;如有侵权立即删除&#xff1b; 庆科官方提供了三种烧录方式&#xff0c;我这边只记…