一、Node简介
1.1 Node是什么
Node.js®是基于 Chrome的V8 JavaScript 引擎构建的JavaScript运行环境、运行时(runtime)。
Node.js不是新语言,也不是一个框架或者一个库,而是一个软件。2009出现的。
Node.js是一个 JavaScript 运行环境 ,说白了,就是用来运行js的。
中文官网:https://nodejs.org/zh-cn/
1.2. Node能做什么
Node 打破了过去 JavaScript 只能在浏览器中运行的局面。前后端编程环境统一,大大降低了前后端语言切换的代价。
- Node.js 适合开发服务器端的中间层(BFF)
- Node.js 适合用于开发前端方向的各种工具
以下是Node可以实现的工作:(仅作了解)
- Web 服务器
- 命令行工具
- 网络爬虫
- 桌面应用程序开发(Electron)
- app
- 嵌入式
- 游戏
- ……
1.3. 安装Node
中文官网:https://nodejs.org/zh-cn/
安装后,可打开终端如cmd,输入node -v 查看是否安装成功
二、Node.js 相关工具
2.1 nvm
我们知道,NodeJS有太多的版本了,切记,并不是新版本一出现,旧的版本就不去用了。
在不同的项目开发过程中,可能需要我们在电脑中同时存在多个不同版本的Node。
这时候就需要一个软件,来更好地管理这些不同版本地Node存在我们地电脑中,Nvm就是这样一个软件。
nvm (node.js version manager 的简写)翻译过来 nodejs 版本管理器。
2.1.1 安装Nvm
nvm下载链接 https://github.com/coreybutler/nvm-windows/releases
注意:如果电脑之前安装过nodejs,请先卸载nodejs后再进行安装。
检测nvm是不是安装成功了:
成功安装后,新开一个 cmd 窗口,输入 nvm -v 如果有信息,代表安装成功!
配置nvm:
复制下面两句话到nvm的安装目录的settings.txt的最后。
(目的是加快后面下载nodejs的速度)
node_mirror: https://npm.taobao.org/mirrors/node/npm_mirror: https://npm.taobao.org/mirrors/npm/
2.1.2 nvm命令
- nvm version: 查看 nvm 的版本
- nvm list: 查看当前安装的 Node.js 所有版本 (常用)
- nvm install 版本号 [架构]: 安装指定版本的 Node.js (常用)
- nvm uninstall 版本号: 卸载指定版本的 Node.js
- nvm use 版本号: 选择指定版本的 Node.js (常用)
# 安装指定版本nvm install 10.15.0# 安装最新版本nvm install latest# 使用安装的这个版本10.15.0nvm use 10.15.0# 查看node版本node -v
2.2 npm
npm 全称为 Node Package Manager,是一个基于 Node.js 的包管理器,也是整个 Node.js 社区最流行、支持的第三方模块最多的包管理器。npm的初衷:JavaScript开发人员更容易分享和重用代码。
npm 全称为 Node Package Manager,是一个基于 Node.js 的包管理器,也是整个 Node.js 社区最流行、支持的第三方模块最多的包管理器。npm的初衷:JavaScript开发人员更容易分享和重用代码。
- nodejs = ECMAScript + 核心模块
- 自己遵循 commonjs 规范写出模块,如果写的是功能模块(日期处理datejs,数字处理numberjs)。如果可以把这些模块分享出来,以后谁要进行相关功能开发的时候,直接拿开发好的模块使用即可,没必要自己在开发。在互联网有一个网站专门收集这样的工具包。https://www.npmjs.cn/。
- 如果我们要使用这个网站里面的包,则我们需要使用一个功能,叫做 npm。
npm可以用来:
- 允许用户获取第三方包并使用
- 允许用户将自己编写的包或命令行程序进行发布分享
2.2.1 npm安装
npm不需要单独安装。在安装 Node 的时候,会连带一起安装npm。
执行下面的命令可以用来查看本地安装的 npm 的版本号。
npm -v
如果想升级 npm ,可以这样
npm install npm --global(-g)
- 在nodejs安装的根目录下新建 node_cache 和 node_global 两个文件夹。
- 分别使用以下命令设置全局的安装包目录:
npm config set prefix “D:\Program Files\nodejs\node_global”
npm config set cache “D:\Program Files\nodejs\node_cache” - 配置环境变量:
打开计算机的环境变量,找到系统变量,新增一项 NODE_PATH,值为安装目录下的nodejs, D:\Program Files\nodejs\node_global\node_modules
2.2.2 npm常用命令
- npm help 查看所有命令
npm help xxx 查看某条命令的详细帮助 - npm install (i) xxx 本地安装
npm install (i) xxx -g 全局安装 - npm list (ls) -g 查看所有全局安装的模块信息,list 可以简写为 ls
npm list (ls) —depth=0 xxx 查看某个安装的模块信息,第一层 - npm uninstall (uni) xxx 卸载模块
- npm update xxx 更新模块
- npm search xxx 搜索模块
- npm init 创建模块
- npm update
可以把当前目录下 node_modules子目录里边的对应模块更新至最新版本
npm update-g 全局更新 - npm root -g 查看全局包安装位置
npm 安装模块
npm init # npm 初始化当前目录
npm i # 安装所有依赖
npm i express # 安装模块到默认dependenciesnpm i express -g # 会安装到配置的全局目录下npm i express -S # 安装包信息将加入到dependencies生产依赖npm i express -D # 安装包信息将加入到devDependencies开发依赖npm i jquery@1.8.3 # 安装jquery指定的1.8.3版本
npm 卸载模块
npm uninstall express # 卸载模块,但不卸载模块留在package.json中的对应信息npm uninstall express -g # 卸载全局模块npm uninstall express --save # 卸载模块,同时卸载留在package.json中dependencies下的信息npm uninstall express --save-dev # 卸载模块,同时卸载留在package.json中devDependencies下的信息
npm 更新模块
npm update jquery # 更新最新版本的jquerynpm update jquery@2.1.0 # 更新到指定版本号的jquerynpm install jquery@latest # 可以直接更新到最后一个新版本
npm 查看命令
npm root # 查看项目中模块所在的目录npm root -g # 查看全局安装的模块所在目录npm list 或者 npm ls # 查看本地已安装模块的清单列表npm view jquery dependencies # 查看某个包对于各种包的依赖关系npm view jquery version # 查看jquery最新的版本号npm view jquery versions # 查看所有jquery历史版本号(很实用)npm view jquery # 查看最新的jquery版本的信息npm info jquery # 查看jquery的详细信息,等同于上面的npm view jquerynpm list jquery 或 npm ls jquery # 查看本地已安装的jquery的详细信息npm view jquery repository.url # 查看jquery包的来源地址
npm 其他命令
npm cache clean --force # 清除npm的缓存npm prune # 清除项目中没有被使用的包npm outdated --long (-l) # 检查模块是否已经过时npm repo jquery # 会打开默认浏览器跳转到github中jquery的页面npm docs jquery # 会打开默认浏览器跳转到github中jquery的README.MD文件信息npm home jquery # 会打开默认浏览器跳转到github中jquery的主页
npm dedupe
命令用于删除重复的依赖项。它通过删除重复的包并在多个依赖包之间有效地共享公共依赖项来简化整体结构。它会产生一个扁平的和去重的树。npm dedupe 或 npm ddp
npm audit
检查项目依赖项是否存在漏洞。它可以看出有风险的 package、依赖库的依赖链、风险原因及其解决方案。npm audit
- 如果发现存在漏洞,我们可以使用 npm audit fix,它将自动安装所有易受攻击依赖包的修补版本(如果可用)。
npm audit fixnpm audit fix --force - 更好的做法是使用 synk,它是一个高级版的 npm audit,可自动修复,且支持 CI/CD 集成与多种语言。
npx snyk
npm doctor
命令可以在我们的环境中运行多项检查。npm doctor
2.2.3 package.json和包的安装
# package.json初始化npm init -y# 安装包到生产环境(用户需要安装的),默认就是这个npm install jquery --save(-S)# 安装包到开发环境(用户可以不安装的)npm install lodash --save-dev(-D)# 查看包的所有版本npm view jquery versions# 安装包的指定版本npm install jquery@2.2.2# 卸载包npm uninstall jquery# 查看所有本地包的最新情况npm outdated# ~2.0.0表示patch, ^2.0.0表示minor * 表示xx最新版本# 更新包npm update# 清除缓存,--force 是强制执行npm cache clean --force# 查看全局包安装位置npm root -g
2.2.4 package.json
{"name": "liwker-test", // 包名"version": "1.0.1", // 版本号"description": "", // 描述"main": "index.js", // 入口文件"scripts": { // 脚本"test": "echo \"Error: no test specified\" && exit 1"},"keywords": [],"author": "Liwker","license": "ISC","dependencies": {"lodash": "^4.17.21"}}
2.2.5 npm 包版本符号
- ^ : 锁定major,第一个数
- ~ : 锁定minor,第二个数
- 空 : 锁定patch,第三个数(偶数为稳定,奇数为不稳定)
- *: 最新版本
"dependencies": {"jquery": "^3.6.0"}
2.2.6 上传自己的包
- 编写模块,保存为 index.js
exports.sayHello = function(){return 'Hello World';}
- 注册npm仓库账号(https://www.npmjs.com/) ```bash npm adduser
// 不是第一次登录 npm login
3. 上传包```bashnpm pubish
可以失败的原因:
切换npm源方法一
npm config set registry http://registry.npmjs.org
切换npm源方法二,需要安装nrm
nrm use npm
2. Err 400<br />我就踩了这个坑<br />一是在注册账号后需要邮箱的验证<br />二是package.json中的name值也就是包的名字必须是**全网唯一的**<br />三是包的名字**不能有大写字母**上传好了后,可以在[https://www.npmjs.com/](https://www.npmjs.com/)搜到自己的包<br />就可以 npm install 自己的包4. 卸载包```bash# 查看当前项目引用了哪些包 :npm ls# 卸载包:npm unpublish --force
2.2.7 npm脚本
Node 开发离不开 npm,而脚本功能是 npm 最强大、最常用的功能之一。
1 什么是 npm 脚本?
npm 允许在 package.json 文件里面,使用 scripts 字段定义脚本命令。
{// ..."scripts": {"build": "node build.js"}}
2 执行顺序
如果 npm 脚本里面需要执行多个任务,那么需要明确它们的执行顺序。
"scripts": {"script1": "node script1.js","script2": "node script2.js"}
如果是并行执行(即同时的并行执行),可以使用 & 符号。
npm run script1 & npm run script2
如果是继发(串行)执行(即只有前一个任务成功,才执行下一个任务),可以使用 && 符号。
npm run script1 && npm run script2
多脚也可以写在json里
// 并行执行"scripts": {"start": "node script1.js & node script2.js"}// 串行执行"scripts": {"start": "node script1.js && node script2.js"}
3 简写形式
常用的 npm 脚本简写形式。
npm start 是 npm run startnpm test 是 npm run test
4 变量
npm 脚本有一个非常强大的功能,就是可以使用 npm 的内部变量。
首先,通过 npm_package_ 前缀,npm 脚本可以拿到 package.json 里面的字段。比如,下面是一个 package.json。
注意:一定要在 npm 脚本中运行(如:npm run view)才可以,直接在命令行中运行JS(如:node view.js)是拿不到值的
{"name": "foo","version": "1.2.5","scripts": {"view": "node view.js"}}
那么,变量 npm_package_name 返回 foo,变量 npm_package_version 返回 1.2.5。
// view.jsconsole.log(process.env.npm_package_name); // fooconsole.log(process.env.npm_package_version); // 1.2.5
上面代码中,我们通过环境变量 process.env 对象,拿到 package.json 的字段值。如果是 Bash 脚本,可以用$npm_package_name 和 $npm_package_version 取到这两个值。
2.2.8 npm 安装 git 上发布的包
# 这样适合安装公司内部的git服务器上的项目npm install git+https://git@github.com:***.git# 或者以ssh的方式npm install git+ssh://git@github.com:***.git
2.2.9 cross-env 使用
- cross-envs 是什么
运行跨平台设置和使用环境变量的脚本
- 出现原因
当您使用 NODE_ENV=production, 来设置环境变量时,大多数 Windows 命令提示将会阻塞(报错)。(异常是Windows上的Bash,它使用本机Bash。)换言之,Windows 不支持 NODE_ENV=production 的设置方式。
- 解决
cross-env 使得您可以使用单个命令,而不必担心为平台正确设置或使用环境变量。这个迷你的包(cross-env)能够提供一个设置环境变量的 scripts,让你能够以 Unix 方式设置环境变量,然后在 Windows 上也能兼容运行。
- 安装
npm install cross-env -D
- 使用
{"scripts": {"build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js"}}
NODE_ENV环境变量将由 cross-env 设置 打印 process.env.NODE_ENV === ‘production’
2.3. nrm
NRM(npm registry manager) npm源管理
2.3.1 手工切换源
1 查看当前源
npm config get registry
2 切换淘宝源
npm config set registry https://registry.npm.taobao.org
2.3.2 NRM 管理源
NRM (npm registry manager)是npm的镜像源管理工具,有时候国外资源太慢,使用这个就可以快速地在 npm 源间切换。
1 安装 nrm
在命令行执行命令,npm install -g nrm,全局安装nrm。
2 使用 nrm
执行命令 nrm ls 查看可选的源。 其中,带*的是当前使用的源,上面的输出表明当前源是官方源。
如果安装成功,执行不起,显示:path.js:39 throw new ERR_INVALID_ARG_TYPE(‘path‘, ‘string‘, path)解决问题:1、运行,npm ls命令,找到npm的安装路径。2、在资源管理器中,找到nrm的安装目录,一般是:C:\Users\Administrator\AppData\Roaming\npm\node_modules\nrm3、在目录下找到cli.js文件。4、用文本编辑器打开它。修改里面的一行代码:原来代码是:const NRMRC = path.join(process.env.HOME, '.nrmrc');修改为:const NRMRC = path.join(process.env.USERPROFILE, '.nrmrc');5、重新运行,nrm ls成功。
3 切换 nrm
如果要切换到taobao源,执行命令 nrm use taobao
4 测试速度
你还可以通过 nrm test 测试相应源的响应时间。
nrm test
2.4 npx
npx: npm package extention
npm 从5.2版开始,增加了 npx 命令。它有很多用处,本文介绍该命令的主要使用场景。
Node 自带 npm 模块,所以可以直接使用 npx 命令。万一不能用,就要手动安装一下。
npm install -g npx
2.4.1 调用项目安装的模块
npx 想要解决的主要问题,就是调用项目内部安装的模块。比如,项目内部安装了Mocha。
npm install -D mocha
一般来说,调用 Mocha ,只能在项目脚本和 package.json 的scripts字段里面,如果想在命令行下调用,必须像下面这样。
# 项目的根目录下执行node-modules/.bin/mocha --version
npx 就是想解决这个问题,让项目内部安装的模块用起来更方便,只要像下面这样调用就行了。
npx mocha --version
npx 的原理很简单,就是运行的时候,会到node_modules/.bin路径和环境变量$PATH里面,检查命令是否存在。
由于 npx 会检查环境变量$PATH,所以系统命令也可以调用。
# 等同于 lsnpx ls
注意,Bash 内置的命令不在$PATH里面,所以不能用。比如,cd是 Bash 命令,因此就不能用npx cd。
2.4.2 —no-install 参数和 —ignore-existing 参数
如果想让 npx 强制使用本地模块,不下载远程模块,可以使用--no-install参数。如果本地不存在该模块,就会报错。
npx --no-install http-server
反过来,如果忽略本地的同名模块,强制安装使用远程模块,可以使用--ignore-existing参数。比如,本地已经安装了http-server,但还是想使用远程模块,就用这个参数。
npx --ignore-existing http-server
2.5 noddmon
在使用node的一些比如http模块写web服务器,但是每次改写一点代码都需要重启服务器,开发不是很方便。nodemon可以监听代码的改动自动更新,不需要重启服务器程序就可以看效果。
文档:https://www.npmjs.com/package/nodemon
下载:
npm install -g nodemon
2.6 相关文档
- http://www.ruanyifeng.com/blog/2019/02/npx.html
- npm 模块管理器
- npm 模块安装机制
- nrm
- http://www.ruanyifeng.com/blog/2019/02/npx.html
- https://github.com/zkat/npx
- https://www.jianshu.com/p/cee806439865
三、模块/包 与CommonJS
Node.js 有三类模块,即内置的模块、第三方的模块、自定义的模块。
3. 1 内置的模块
Node.js 内置模块又叫核心模块,Node.js安装完成可直接使用。如:
const path = require('path')var extname = path.extname('index.html')console.log(extname)
3.2 第三方的Node.js模块
第三方的Node.js模块指的是为了实现某些功能,发布的npmjs.org上的模块,按照一定的开源协议供社群使用。如:
npm install chalkconst chalk = require('chalk')console.log(chalk.blue('Hello world!'))
3.3 自定义的Node.js模块
自定义的Node.js模块,也叫文件模块,是我们自己写的供自己使用的模块。同时,这类模块发布到npmjs.org上就成了开源的第三方模块。
自定义模块是在运行时动态加载,需要完整的路径分析、文件定位、编译执行过程、速度相比核心模块稍微慢一些,但是用的非常多。
3.3.1 模块定义、接口暴露和引用接口
我们可以把公共的功能 抽离成为一个单独的 js 文件 作为一个模块,默认情况下面这个模块里面的方法或者属性,外面是没法访问的。如果要让外部可以访问模块里面的方法或者属性,就必须在模块里面通过 exports 或者 module.exports 暴露属性或者方法。
m1.js:
const name = 'Liwker'const sayName = () => {console.log(name)}console.log('module 1')// 接口暴露方法一:module.exports = {say: sayName}// 接口暴露方法二:exports.say = sayName// exports是对 module.exports 的引用// 相当于 exports = module.exports// 所以下面这种是错误的!/*exports = {say: sayName}*/
main.js:
// 引用模块const m1 = require('./m1.')m1.say()
四、常用内置模块
三、 全局对象 global
JavaScript 中有一个特殊的对象,称为全局对象(Global Object),它及其所有属性都可以在程序的任何地方访问,即全局变量。
在浏览器 JavaScript 中,通常 window 是全局对象, 而 Node.js 中的全局对象是 global,所有全局变量(除了 global 本身以外)都是 global 对象的属性。
后面看到所有的全局变量,例如 console,setTimeout 和 process 是 global 变量的成员。我们甚至可以向全局变量添加成员,使其在任何地方都可用。
// 1. nodejs 里面声明的变量,并不会被挂载带 global 全局对象let b = 20;console.log(global.b); //undefined// 2. 可以向global添加成员,使其在任何地方都可用global.a = 10;console.log(a); //10// 3. 在nodejs执行js文件的过程中,里面也存在 this ,但是这个 this 和 global 并不是相等。console.log(global === this); //false// 实际上,在 nodejs 里面的this代表的当前这个 js模块(暂且认为 this 代表当前这个js文件)
process 对象
console.log(process.argv);// 返回一个数组,前两个值是 node 命令所在位置,被执行 JS 文件的路径,若你执行命令时还有带有参数,依次会填充到此数组中也打印出来。(使用 nodejs 开发命令行的应用,需要获取 命令行的参数,才用得上)console.log(process.argv.slice(2));node process.js argv1 argv2// 打印命令里的后两个参数 [argv1, argv2]console.log(process.arch); // 打印系统位数 x64
5.6 yarn
Yarn 是于 2016 年 10 月 由 Facebook、Google、Exponent 和 Tilde 联合推出了一个新的 JS 包管理工具,旨在取代 npm 这种包管理工具。
官网:
https://yarnpkg.com/en/docs
中文参考链接:
https://yarn.bootcss.com/
特点:
- 速度超快
yarn 缓存了每个下载过的包,所以再次使用时无需重复下载。 同时利用并行下载以最大化资源利用率,因此安装速度更快。 - 超级安全
在执行代码之前,yarn 会通过算法校验每个安装包的完整性。 - 超级可靠
使用详细、简洁的锁文件格式和明确的安装算法,yarn 能够保证在不同系统上无差异的工作。
安装:
管理员模式运行cmd :npm install -g yarn
常用命令:
| npm | yarn |
|---|---|
| npm init -y | yarn init -y |
| npm install 包名 [—save] | yarn add 包名 |
| npm uninstall react [—save] | yarn remove [react] |
| npm install react —save-dev | yarn add react —dev |
| npm update [—save] | yarn upgrade |
| npm install -g @vue/cli | yarn global add @vue/cli |
yarn 全局安装后,命令不生效
背景:
- 执行
yarn global add @vue/cli后,重启bash......, vue 命令依然不生效 - 而 npm 全局安装(npm install -g @vue/cli)后,命令生效
解决办法:
1.执行如下命令,得出 yarn 全局安装的命令所处的安装目录
yarn global bin
2.复制安装目录至电脑的环境变量中
修改yarn全局安装路径
- 改变 yarn 全局安装位置
#1.改变 yarn 全局安装位置yarn config set global-folder "你的磁盘路径"#这里是我的路径yarn config set global-folder "D:\tools\Yarn\Data"
- 改变 yarn 缓存位置
#2. 改变 yarn 缓存位置yarn config set cache-folder "你的磁盘路径"#这里是我的路径yarn config set cache-folder "D:\tools\Yarn\Cache"
- 改变yarn bin位置
在我们使用全局安装包的时候,会在 “D:\tools\Yarn\Data” 下 生成node_modules\.bin目录
#3.改变 yarn bin位置yarn config set prefix "你的磁盘路径"#这里是我的路径yarn config set prefix "D:\tools\Yarn"#安装全局包后,会在设置的路径下生成一个bin文件夹
我们需要将 D:\tools\Yarn\bin 整个目录 添加到系统环境变量中去,否则通过yarn 添加的全局包 在cmd 中是找不到的。
检查当前yarn 的 bin的 位置
yarn global bin#如果按上面设置好了的就会是 "D:\tools\Yarn\bin"
检查当前 yarn 的 全局安装位置
yarn global dir#如果按上面设置好了的就会是 "D:\tools\Yarn\Data"
四、模块 使用
4.1 模块规范定义
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
模块化的优势有以下几点:
- 防止命名冲突
- 代码复用
- 高维护性
一个js文件就是一个模块,模块的作用域是私有的,内部定义的变量或者函数,只在当前的文件(模块)可以使用
如果别人需要使用我们模块里面的东西,那么有两点要做(以CommonJS 的 Modules 规范: Node.js为例)
- 自己编写的模块,由于模块作用域是私有的,默认情况下,外部是没办法使用的;如果希望别人可以使用,则需要导出
exports或者module.exports。 导出的时候,以对象的方式进行导出 - 别人要使用某个模块,则需要先引入该模块,使用
require引入,引入后需要使用一个变量来接收导入的对象。
对书写格式和交互规则的详细描述,就是模块定义规范(Module Definition Specification):
- AMD 规范: Require.js
- CMD 规范: Sea.js
- CommonJS 的 Modules 规范: NodeJs
- ES6 模块化规范 import … from …
4.2 NodeJs 模块化使用
导出数据方式一:
exports.num = num;exports.sum = sum;exports.Animal = Animal;
导出数据方式二:
// 通过module.exports 等于一个对象,来导出数据// 对象可采用es6简化对象的写法module.exports = {num,sum,Animal};
导入数据:
// 注意1: 如果要使用某个模块里面的数据,则需要使用 require 关键字进行导入。// 注意2:在导入用户自己开发的模块的时候,需要加上路径(1. 相对路径(多) 2. 绝对路径) 注意: ./ 必须写上// 注意3:模块文件的扩展名(后缀名)可以写,也可以不写// 注意4:导出的模块一般需要使用一个变量来接收,一般把接收的量定义为常量// 注意5: 定义常量的名称和文件的名称保持一致(这个不是必须,大家都这么做)const m1 = require("./modules/m1.js");
完整代码:
// 导出,m1.js中:let num = 10;function sum(a, b) {return a+b}class Animal{constructor(){this.age=0}}// 导出数据方式1:// exports.num = num;// exports.sum = sum;// exports.Animal = Animal;// 导出数据方式2:// 通过module.exports 等于一个对象,来导出数据// 对象可采用es6简化对象的写法module.exports = {num,sum,Animal};
//导入,使用模块const m1 = require("./modules/m1.js");console.log(m1); //{ num: 10, sum: [Function: sum], Animal: [Function: Animal] }console.log(m1.sum(10, 20)); // 30const obj = new m1.Animal();console.log(obj.age); // 0
4.3 模块里面this的指向问题
exports 实际上是 module.exports 的引用
在 nodejs 里面的 this 代表当前的这个模块,也就是 exports 对象(在文件里,不是交互终端)
console.log(exports); //{}console.log(module.exports); //{}console.log(exports === module.exports); //true exports实际上是module.exports的引用console.log('this', this); // this {}console.log(this === exports);// true// 在 nodejs 里面的 this 代表当前的这个模块,也就是 exports 对象 并且,交互模式下,没有exports这个对象console.log(global === this ); //false this不指向全局对象
4.4 nodejs常用内置模块
一般项目中模块分为3种:
- node.js 内置模块
- 自己书写的模块
- 第三方模块(使用一个专门的工具npm进行统一管理)
常用的内置模块如下:
- fs :文件操作
- http :网络操作
- path :路径操作
- querystring :查询参数解析
- url :url 解析
const fs = require("fs");const http = require('http');const path = require('path');const querystring = require('querystring');const url = require('url');
nodejs内置模块的文档网址:http://nodejs.cn/api/
4.5 path 内置模块
path 模块,处理与路径相关
// 导入模块const path = require("path");console.log(__dirname); // 当前执行的文件绝对路径,不包含文件名console.log(__filename); // 当前执行的文件绝对路径,包含文件名和后缀名let extname = path.extname( __filename ); // 获取扩展名(后缀名)console.log(extname);let baseName = path.basename( __filename ); // 获取文件名(包含后缀名)console.log(baseName);let dirname = path.dirname(__filename); //获取目录(路径)console.log(dirname);let parse = path.parse(__filename); //获取路径字符串的对象console.log(parse);//路径的拼接操作 join// join 默认相对路径的拼接 ,以当前操作系统路径分割符进行拼接let fullPath1 = path.join('path.js');// fullPath1 = path.join(__dirname,'path.js'); //带目录// fullPath1 = path.join(__dirname,'a','path.js'); //带多级目录console.log(fullPath1);
4.6 Buffer 数据类型
JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。但在处理像文件流时(文件读写操作),必须使用到二进制数据。因此在 Node.js 中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。说白了,Buffer 类似于一个整数数组。
创建buffer对象 :
let buf1 = Buffer.from([97, 98, 99]); //根据一个数组创建 Buffer 对象console.log(buf1); //<Buffer 61 62 63> 以16进制存在buffer对象中console.log(buf1.toString()); // abclet buf2 = Buffer.from("nodejs"); //根据一个字符串创建 Buffer 对象console.log(buf2);console.log(buf2.toString()); // nodejslet buf3 = Buffer.alloc(10); // 创建了可以存放10个字符的buffer对象buf3.write("abc"); //按照ASCII表的值,转16进制,存在buffer中console.log(buf3);console.log(buf3.toString()); // abc// 总结: 以后看到 <Buffer ..... > 需要 toString() 才能看到里面的真实数据
4.7 fs 文件系统模块
Node.js 的 API 内置的有两个模块: path 和 fs ,我们使用 JavaScript 代码编写程序运行在 Node.js 环境中就可以操作文件
4.7.1 同步读取文件信息
同步读取:读取的时候,要等文件读取完毕后,才会执行后面的代码 (sync 同步)
// 准备工作const fs = require("fs");const path = require("path");let pathName = path.join(__dirname, 'hello.txt');//同步读取文件const content = fs.readFileSync(pathName);// console.log(content);// 转换console.log(content.toString());const content = fs.readFileSync(pathName, "utf-8");console.log(content);
4.7.2 异步读取文件信息
不用等待文件读取完毕就会执行后面的代码。所谓异步,就是当前回调函数不用等执行完就可以执行后面的语句。
思考:如何读到后面的数据
答:在读取文件的时候,传递一个回调函数callback,当读取完毕后,回调函数执行,读取后面的数据
const fs = require("fs");const path = require("path");let pathName = path.join(__dirname, "hello2.txt");// console.log(file);//参数1 要读取的文件//参数2 设置读取到内容的编码,设置后读到的内容为字符串,如果不传则读到的数据为 buffer//参数3 回调函数,读取完文件后执行的代码fs.readFile(pathName, "utf-8",(error, data)=>{// console.log(error);// console.log(data);if(error){console.log(error);return;}console.log(data);});
4.7.3 异步写入
const fs = require("fs");const path = require("path");let pathName = path.join(__dirname, "hello.txt");fs.writeFile(pathName, "hello_write111", "utf-8",(error)=>{console.log("error");console.log("写完啦");});console.log("end");
4.7.4 几个常见方法
const fs = require("fs");fs.renameSync(旧文件名, 新文件名); //修改文件名fs.readdirSync(__dirname); //读取当前路径下的文件名列表let str = "hello";str.endsWith("lo"); //true 是否以某字符串结尾str.startsWith("hh"); //false 是否以某字符串开头str.substring(2,4) //ll 左闭右开区间str.substring(2) //llo 从下标为2取到结束
4.7.5 小案例
需求:把当前文件夹的js文件的名字都添加前缀 [Liwker]
const fs = require("fs");let nameList = fs.readdirSync(__dirname);nameList.forEach(currFileName => {if(currFileName.endsWith(".js")){fs.renameSync(currFileName, `[Liwker]${currFileName}`)}});
需求:把当前文件夹的名字都删除前缀 [Liwker]
const fs = require("fs");let nameList = fs.readdirSync(__dirname);let str1 = "[Liwker]"nameList.forEach(currFileName => {if(currFileName.startsWith(str1)){fs.renameSync(currFileName, currFileName.substring(str1.length))}});
4.8 http 模块
4.8.1 http核心模块的使用
四个步骤:
- 导入http模块
- 定义服务器程序端口
- 创建服务器对象
- 调用服务器的监听方法,让服务器监听浏览器请求
// 1、导入http模块const http = require("http");// 2、定义服务器程序端口const port = 8080;// 端口号:1-65535 (有些服务已经有一些默认端口 apache nginx 80 web 服务。 MySQL:3306 MongoDB:27017)// 注意:一个端口只能被一个服务进行使用,如果这个端口被某个服务使用,其他的服务不能在使用该端口的。这个时候出现端口冲突。如何解决?答:换个端口// 建议:1-1024 端口(有些系统服务会使用这个范围的端口),不建议程序员自己使用。一般都使用 1024 以后的端口。// 3、创建服务器对象const server = http.createServer((request, response)=>{response.write("hello nodejs"); // 书写响应体内容response.end() //发生响应到浏览器 当我们修改代码后,需要重新执行该文件,重启服务});// 4、调用服务器的监听方法,让服务器监听浏览器请求server.listen(port,(error)=>{console.log(error);console.log(`server is running at port ${port}`);});
//如果需要解决中文乱码,需遵循http协议:response.setHeader("Content-type","text/html;charset=utf-8");
4.8.2 获取请求的一些信息
const http = require("http");const url = require("url");const server = http.createServer((request, response)=>{//如果需要解决中文乱码,需遵循http协议:response.setHeader("Content-type","text/html;charset=utf-8");console.log("------------------------------");// Getlet requestUrl = request.url; // 获取本次请求的资源路径console.log(requestUrl);let method = request.method; // 获取本次请求的方式console.log(method);let obj = url.parse( requestUrl, true); // true解析成对象,false解析成字符串console.log(obj.query); // 获取get请求的查询字符串// localhost:8080?name=nodejs&age=11 get请求// Post//当存在 post 提交数据 data 事件立马执行,postData就是提交过来的数据对象request.on('data',(postData) => { // 获取post请求的请求参数console.log(postData.toString());});response.write("hello nodejs"); // 书写响应体内容response.end(); //发生响应到浏览器 当我们修改代码后,需要重新执行该文件,重启服务});
六、ES6模块
6.1 nodejs12版本以下是 不支持ES6模块化规范的解决方案
在项目目录下新建src文件夹,src文件夹下新建m1.js模块和app.js模块:
m1.js模块中到处数据:
export let name = "nodejs";export let age = 11;
app.js中导入模块:
import {name,age} from "./m1.js"
此时运行app.js会报错!!! SyntaxError: Unexpected token {
注意:nodejs 不支持 es6 模块化规范。
可以把这个代码转换一下,然后把 es6 规范转换为 commonjs 规范
学语法,兼容性如何不用管,可以交给第三方的转换工具(babel-cli 和 browserify)实现
解决:
1、在项目文件夹下生成生成 package.json 文件
yarn init -y 或者 npm init -y
2、安装第三方工具:
在任意目录下执行,全局安装babel-cli 和 browserify:
如果yarn没有安装成功,就用npm
yarn global add babel-cli browserify 或者 npm install babel-cli browserify -g
在自己项目目录下执行:
yarn add babel-preset-es2015 或者 npm install babel-preset-es2015 --save-dev
3、在项目根目录新建 .babelrc 文件 :
{"presets": ["es2015"]}
4、在项目目录下书写完代码后,执行:
babel src -d lib// src(源文件夹) lib(目标文件夹)
(如果出现babel 不是内部或者外部命令,请按照第三点最后的yarn 全局安装后,命令不生效的解决办法)
5、运行lib下的app.js即可 node lib\app.js
(记得,修改代码需要执行babel src -d lib命令后,再运行lib下的app.js)
6.2 ES6模块化规范语法
导出数据方式一:
//导出数据方式一:export let name = "nodejs";export let age = 11;
导出数据方式二:
let name = "nodejs";let age = 11;export {name, age}
针对导出数据的前两种方式的导入数据:
import {name,age} from "./m1.js"
导出数据方式三:
// 默认导出只能写一次export default {name, age}
导入并使用数据:
import m3 from "./m3"console.log(m3.name);console.log(m3.age);
在es6中的默认导出的写法,允许和前面的导出方式一起写:
导出数据:
let name = "nodejs";let age = 11;export let email = "nodejs@163.com";// 默认导出只能写一次export default {name, age}
导入并使用数据:
import m3, {email} from "./m3"console.log(m3.name);console.log(m3.age);console.log(email);
