Node学习的第一天
Node是什么
说明:node是一个
js的运行环境
可以说node的产生使得js不仅仅在浏览器上运行,也可以在服务器上运行
;node是一门技术
,基于Chrome V8
引擎的JavaScript运行时
优点:1. 使用node可以
减少
很多不必要的兼容性
问题(因为基于谷歌的环境,基本没有太多的兼容性问题)
2. IO处理非常快,对数据处理
速度是相比其他的最快
的
3. 所用的语言是JavaScript的,只有一条主线程
,用起来很方便,没有线程切换的损耗,没有线程之间的竞争
js与浏览器的关系
说明:js是一门
解释型
,弱类型
,编译型
的语言,与浏览器是解释器
的关系
Node中的js与浏览器中的js的对比
Node中的js组成:JavaScript + ECMAScript +
Node API
,提供了较为完整的控制计算机
的能力,通过Node提供的接口,实现对整个操作系统的控制
浏览器中的js组成:JavaScript + ECMAScript +
WEB API
(BOM操作,DOM操作,Ajax),在浏览器上运行的js有很大的局限性
,会有http的同源策略限制跨域无法访问,文件读写也完成不了;
运行Node
说明:运行node打开cmd,输入node进入当有光标闪烁时表示正在运行
进入repl交互式
运行环境若需要将js文件放在node上运行则先切换到js文件
所在的目录后再node js文件名
全局对象(global)
说明:在浏览器中顶级对象window可以用由普通函数中的this去指向,在Node中顶级对象是global也只能用global表示即:
浏览器中的window相当于Node中的global
,当两者的this指向不一样,浏览器
中this指向window
,在Node
中运行的js文件里的this不指向
global
特别:console.log输出语句在浏览器上与Node上是
通用
的
代码演示
//在浏览器上打印this
console.log(this)//window
console.log(this === window)//true
//在Node上打印this与global
console.log(this) //{}一个空对象
console.log(global) // global对象的对象
console.log(this === global)
运行在cmd效果图
浏览器中的setTimeout与Node中的setTimeout区别
说明:两者用法一样,只是返回值不同;在浏览器中setTimou的返回值是一个随机id,而在Node中setTimeout的返回值是一个Timeout对象
代码演示
const timer = setTimeout(()=>{},10)
//在浏览器端
console.log(timer)// 176100 随机id
//在node上运行
console.log(timer)// 一个Timeout对象
cmd运行效果图
补充:node中的setImmediate类似于浏览器上的setTimeout时间间隔为0时
代码演示
setImmediate(()=>console.log('我是一次性定时器的孪生兄弟'),0)
setTimeout(()=>console.log('我是正牌一次性定时器'),0)
cmd效果演示
__dirname
说明:获取当前cmd开启窗口的文件目录的绝对路径(该属性不是global的)
代码演示
console.log(__dirname)
cmd运行效果
__filename
说明:获取当前cmd运行的文件的绝对路径(该属性不是global的)
代码演示
console.log(__filename)
cmd运行效果
Buffer
说明:Buffer是一种
类型化
的数组,继承Uint8Array
,也是数据的传输格式,传输的数据是以16位
进制的数进行传输的,Buffer是可转变
的
代码演示
//转化为Buffer字节
const buffer = Buffer.from('小猪佩奇')
console.log('buffer:',buffer)
//将Buffer字节转化为字符串
const str = buffer.toString()
console.log('str:',str)
cmd运行效果
process
说明:process对象是
global
提供有关当前Node.js进程并对其进行控制的信息,可以作为全局对象
使用
cwd()
说明:process的一个方法可以用来以
字符串
是方式获取当前的命令行的路径
代码演示
// 在node的交互式环境下可以直接调用
process.cwd()
cmd运行效果
exit()
说明:该方法可以
强制退出node
进程,可以传入退出码,0表示成功退出
,一般默认为0,使用该方法主要是为了输入到日志
中,方便以后查看bug修改
代码演示
// 在node的交互式环境下可以直接调用
process.exit()
cmd运行效果
argv
说明:返回一个包含启动Node.js进程时传递的
命令行参数的数组
。第一个参数是启动Node.js进程的可执行文件的绝对路径
名,第二个参数是当前执行的js文件的绝对路径
,其他的参数就是node命令行之后输入的其他参数
了
代码演示
console.log(process.argv)
cmd运行效果
platfrom
说明:获取当前的平台系统
代码演示
// 在node的交互式环境下可以直接调用
process.platform
cmd运行效果
kill(pid)
说明:根据进程的pid杀死进程
示例演示
// 在node的交互式环境下可以直接调用
process.kill(38200)
cmd运行效果
env
说明:获取环境变量对象
代码演示
//获取环境变量对象中配置的Path值
process.env.Path
cmd效果演示
Node模块化
说明:在Node中提供了很多内置的模块化应用就像js中数组的内置方法
语法:
require()
导入
绝对路径
说明:对盘目录下的文件的地址
示例演示
require('C:\\Users\\LENOVO\\Desktop\\new-start\\Node\\test.js')
cmd效果演示
相对路径
说明:以
当前文件作为根
去找其他的文件的路径
在相对路径中加./
与不加./
的区别
加./:在服务端,一定要加./表示从
当前目录开始
不加./:如果不加./的话,会先去确认是否属于自己的
内置模块
,如果不是那就是无效的路径(报错),如果是内置模块那就会在当前的目录下的node_modules中去找,如果没有就再去上级目录中的node_modules中找一直找到最外层的node_modules中
案例演示
//加./的
require('./test.js')
//不加./的且不属于内置模块的
require('a.js')
//不加./的但属于内置模块的
require('fs')
cmd效果演示
后缀名
说明:在导入的模块中如果不是特别指定的文件可以
忽略后缀名
的书写,在Node环境下会自动补全
缺失的后缀名
补全顺序:js,json,node,mjs
案例演示
require('./test')
cmd效果图
文件名
说明:如果导入的不是一个文件的路径而是一个目录的路径那么会默认导入在该目录下的index.js文件,如果没有index.js文件就会报错了
案例演示
require('../Node/')
cmd效果图
运行node ./
说明:在node中运行js不仅仅限于输入相应的文件名就可以运行,可以用./去运行js文件,只需要在对应的配置文件中配置好要启动的文件就可以
用./去运行
操作:在当前文件夹下一般会有对应的配置文件package.json,如果没有可以在当前文件下运行一下
npm init
进行初始化配置;在整个配置文件中找到main字段
,一般默认值为index.js,将这默认值修改为自己要启动的js就可以了
操作步骤
- 运行npm init 一直下一步(回车键)就可以
- 找到package.json中的main字段并修改该字段中对应的值
- 运行node ./
图示
module对象
说明:记录当前模块相关信息
图示信息
module.exports 与 exports 区别
module.exports:导出模块,可以导出对象也可以导出一个内容;在一个js导出的模块中,最终是
由module.exprots
收集到的一个对象
内一起导出
exports:也是导出模块,直接导出对象或一个内容
注:当js文件在node中运行,其中的this可以等价于module.exports,exports也可以等价于module.exprots
面试案例
this.a = 1
exports.b = 2
module.exports = {
c: 3,
d: 4
}
// 问:最终导出的内容是什么?
// 结果为:{c: 3,d: 4}
// 解释:因为最终是由module.exports导出,在最后又给module.exports重新赋值,所以最后导出的就是module.exports中的内容
//打印 module.exports 与 this 和 exports的关系
console.log(module.exports === this) // true
console.log(module.exports === exports) // true
require函数
说明:导入模块,这个函数
内置
有一个resolve方法
去拼接导入的路径的绝对路径
然后再去调用,在调用时会先检测自己的缓存
中是否带有导入的路径,如果有就直接使用缓存里的,没有就导入拼接的那个绝对路径
模块化原理
说明:当执行一个模块或使用require时会将一个模块放在
函数式的环境
下执行
解释module.exports
// 在导出一个模块时实际上是在函数内调用了一个自己的函数并将module.exports作为一个对象去接收
// require 大致的执行环境
function require(modulPath){
// 检测缓存内是否存在,有就直接用缓存的
if(require.cache[modulePath]){
return require.cache[modulePath]
}
//然后读文件
//然后将所有东西投到一个内置的函数里
function _temp(modules,exports,require,__dirname,__filename){}
//创建 module.exports 对象
module.exports = {}
const exprots = module.exports
//此时借用module.exports 并作为 this 的指向
_temp.call(module.exports,exports,require,__dirname,__filename)
}
基本内置模块
说明:封装在node_modules文件夹下的模块,都是node的
内置模块
,当然也可以自己手动添加一些自己的模块进入node_modules中
使用
案例演示
//写入一段输出放在test.js文件中
console.log('自定义模块')
图示
//导入自定义的内置模块
require('test')
cmd效果图示
os模块
对操作系统的一系列属性查看
arch()
说明:该方法与process.arch()用法一样返回操作系统的cpu架构
演示
//在交互式环境下运行(若在js文件里调用需要导入os模块)
os.arch() // x64
cmd图示
cpus()
说明:该方法用于获取操作系统的各个内核信息,获取length可以得到操作系统的内核数
方法演示
os.cpus().length //12
cmd图示
freemem()
说明:获取电脑剩余的内存,返回的是字节数
方法演示
os.freemem()// 7385534464
cmd图示
homedir()
说明:获取当前操作系统的用户目录
方法演示
os.homedir()
cmd图示
hostname()
说明:获取当前操作系统的主机名
方法演示
os.hostname()
cmd图示
tmpdir()
说明:获取当前操作系统存放临时文件的文件夹地址
方法演示
os.tmpdir()
cmd图示
path模块
说明:对路径地址的一系列操作,但不会判断路径是否有效
basename()
说明:获取一段路径中的最后一个的内容,如果传入两个参数,则第二个参数为后缀名,如果第二个参数传入的后缀名与第一个参数的后缀名相匹配则最后获取的内容的后缀名会省略,如果不相匹配则保持不变
方法演示
//导入path模块,并用一个变量接收
const path = require('path')
const url0 = path.basename('a/b/c/d/j.html')
console.log('url0:',url0)
const url = path.basename('a/b/c/d/j.html','.html')
console.log('url:',url)
const url2 = path.basename('a/b/c/d/g.html','.js')
console.log('url2:',url2)
cmd图示
sep
说明:获取当前操作系统的对文件路径的分隔符
方法演示
//导入path
const path = require('path')
console.log(path.sep) // \
cmd图示
delimiter
说明:获取当前操作系统对特定路径的界定符
方法演示
//进入repl环境中直接调用
path.delimiter
cmd图示
dirname()
说明:获取指定路径中文件的所在目录,传入一个参数(文件路径或目录)即可
方法演示
// 导入模板
const path = require('path')
const res = path.dirname('src/css/index.css')
console.log('res:',res) // res: src/css
cmd图示
extname()
说明:获取传入的文件路径的后缀名
方法演示
const path = require('path')
const res = path.extname(__filename)
console.log('res:',res)// res: .js
cmd图示
join()
说明:拼接路径,在传入的路径中若有
'../'
的会将前一个的路径的最后一个内容忽略
(其实是将这个内容作为’…/‘下的上一级了),若是在拼接中有相同的路径则会将相同的以’…/'显示
案例演示
// 导入path模块
const path = require('path')
const url = 'a/b'
const res = path.join(url,'../','src/index.html')
console.log('res:',res) // res: a/src/index.html
cmd图示
normalize()
说明:会根据当前的操作系统合理的规范化路径
案例演示
//导入模块
const path = require('path')
const res = path.normalize('a\/\/\abd\\/d/f\/w')
console.log('res:',res) // res: a\abd\d\f\w
cmd图示
relative()
说明:可以将传入的路径转化为相对当前文件的路径格式,传入两个参数,第一个参数是当前文件位置,第二个参数是自定义的一个文件位置
案例演示
//导入path模块
const path = require('path')
const res = path.relative(__filename,'./src/css')
console.log('res:',res)// res: ..\src\css
cmd图示
resolve()
说明:转换为绝对路径进行拼接,一般第一个参数是当前cmd窗口的路径用
__dirname
获取
案例演示
//导入path模块
const path = require('path')
const url = path.resolve(__dirname,'./index.html')
console.log('url:',url) //url: C:\Users\LENOVO\Desktop\new-start\Node\index.html
cmd图示
url模块
说明:url模块用于
处理
与解析URL
parse()
说明:将一个以字符串形式的url地址信息转化成对象的url信息,简单点就是将
字符串转化为对象
了
方法演示
//导入url模块
const url = require('url')
const res = url.parse('https://editor.csdn.net/md?not_checkout=1&articleId=114847813')
console.log('res:',res)
cmd图示
pathname
说明:获取并设置URL的路径部分
方法演示
//导入url模块
const url = require('url')
const res = url.parse('https://nodejs.org/dist/latest-v14.x/docs/api/url.html#url_url_pathname').pathname
console.log('res:',res)
cmd图示
format()
说明:将一个对象转换成字符串,传入一个对象即可
方法演示
//导入模块
const url = require('url')
const obj = url.parse('https://www.baidu.com/?tn=78040160_14_pg&ch=8')
console.log('obj:',obj)
const str = url.format(obj)
console.log('str:',str)
cmd图示
util模块
说明:用于对Node内部API的需求使用
callbackify()
说明:将一个异步函数转换成异常优先执行的回调函数
方法示例
//导入util模块
// 创建一个异步函数
function test(durtion){
return new Promise(resolve=>{
setTimeout(()=>resolve(durtion),durtion)
})
}
//传统的输出
test(500).then(data=>console.log(data))
//转换后的新格式
const newTest = util.callbackify(test)
newTest(500,(err,data)=>{
console.log(data)
})
cmd效果图示
promisify()
说明:将一个异步的回调函数改写成promise的
方法演示
//导入util模块
const util = require('util')
//创建一个异步回调函数
function callbackTest(durtion,callback){
setTimeout(()=>{
callback(null,durtion)
},durtion)
}
//改写这个函数
const newTest = util.promisify(callbackTest)
newTest(1000).then(data=>console.log(data))
cmd效果演示
isDeepStrictEqual()
说明:比较两个对象的结构是否一致,不会比较引用地址
方法演示
//导入util模块
const util = require('util')
//创建两个对象
const obj1 = {
a: 123,
b: {
c: 456,
d: {
e: 789
}
}
}
const obj2 = {
a: 123,
b: {
c: 456,
d: {
e: 789
}
}
}
const res = util.isDeepStrictEqual(obj1,obj2)
console.log('res:',res)
cmd效果图示
文件的I/O
说明:对文件进行的读写操作
I/O
说明:I/O是input与output,对外设备的
输入与输出
,一般IO的速度
往往低于内存与和cpu的交互速度
,但node对这一块有很好的处理
fs模块
说明:对文件的处理与读取操作,支持同步执行,异步执行以及promise的写法
fs.readFile
说明:对文件的的读取操作,可传入三个参数,第一个是读取文件的
路径
(一般要配合path模块的resolve拼接出绝对路径),第二个参数是读取文件的编码格式
,第三个参数是一个回调函数(异常优先
处理的函数)
方法演示
// 导入fs、path模块
const fs = require('fs')
const path = require('path')
const url = path.resolve(__dirname,'./test.txt')
// 异步回调的形式写法
fs.readFile(url,'utf8',(err,data)=>{
console.log('异步回调写法:',data)
})
// 同步写法
const sync = fs.readFileSync(url,'utf8')
console.log('同步写法的结果:',sync)
// promise写法
async function pro() {
const res = await fs.promises.readFile(url,'utf8')
console.log('promise的写法:',res)
}
pro()
cmd效果图示
fs.writeFile
说明:向一个指定的文件写入内容,如果是一个不存在的文件路径会
创建
这个目录下的文件并写入
,如果是一个目录则会报错
;可传入四个参数,第一个是文件路径,第二个是写入内容,第三个是可选的表示是覆盖还是追加(默认覆盖),第四个是回调函数提示是否写入成功
方法演示
// 导入fs、path模块
const fs = require('fs')
const path = require('path')
const url = path.resolve(__dirname,'./new.txt')
// 异步回调式写法
fs.writeFile(url,'writeFile刚刚写入的内容',() => console.log('成功写入'))
//读取写入的内容
async function pro(){
const res = await fs.promises.readFile(url,'utf8')
console.log('res:',res)
继续添加写入的内容但不覆盖之前的内容
await fs.promises,wirteFile(url,'追加内容了',{flag: 'a'})
const res2 = await fs.promises.readFile(url,'utf8')
console.log('res2:',res2)
}
pro()
cmd效果图示
综合读文件与写文件完成一次图片的拷贝
说明:图片的编码格式不是字符串的所以不要用utf8就修改readFile的格式
示例
//导入fs、path模块
const fs = require('fs')
const path = require('path')
// 定义图片路径
const url_img = path.resolve(__dirname,'./role.png')
// 定义拷贝的图片路径
const url_copy = path.resolve(__dirname,'./role_copy.png')
// 使用promise的写法读取文件信息
async function pro(from,to){
const content = await fs.promises.readFile(from)
//写入文件
await fs.promises.writeFile(to,content)
console.log('拷贝完成')
}
pro(url_img,url_copy)
cmd效果图示
fs.stat
说明:获取文件或目录的相关信息,可传入三个参数,第一个是文件或目录的路径,第二个是可选参数表示返回值中的数值是否为bigint型(默认为false),第三个参数就是回调函数
方法演示
//导入fs模块
const fs = require('fs')
//异步回调的写法
fs.stat(__dirname,(err,data) => console.log('异步回调的写法:',data))
//promise的写法
async function pro(){
const res = await fs.promises.stat(__dirname)
console.log('promise的写法:',res)
}
pro()
cmd效果图示
size
说明:这个参数表示
文件的大小
,一般在系统中文件夹的大小被认为是0,但是文件夹里的this指针指向文件了,所以文件夹的大小就是0
案例演示
//导入fs、path模块
const fs = require('fs')
const path = require('path')
const url = path.resolve(__dirname,'./test.txt')
async function pro(){
const res = await fs.promises.stat(url)
console.log('文件大小:',res.size)
const res2 = await fs.promises.stat(__dirname)
console.log('文件夹大小:',res2.size)
}
pro()
atime
说明:上次访问的时间,用法与size一样
mtime
说明:上次修改的时间,用法与size一样
ctime
说明:上次状态修改时间,用法与size一样
birthtime
说明:当前文件创建的时间
演示
//导入fs、path模块
const fs = require('fs')
const path = require('path')
async function pro(url){
const res = await fs.promises.stat(url)
console.log('atime:',res.atime)
console.log('mtime:',res.mtime)
console.log('ctime:',res.ctime)
console.log('birthtime:',res.birthtime)
}
pro(__dirname)
cmd效果图示
isDirectory()
说明:调用该方法可以检测传入的路径是文件还是目录,返回布尔值
案例演示
//导入fs、path模块
const fs = require('fs')
const path = require('path')
async function pro(url){
const res = await fs.promises.stat(url)
console.log("判断是否为一个目录:",res.isDirectory())
}
pro(__filename)
cmd效果图示
isFile()
说明:判断是否为一个文件,返回布尔值
案例演示
//导入fs、path模块
const fs = require('fs')
const path = require('path')
async function pro(url){
const res = await fs.promises.stat(url)
console.log('判断是否是一个文件:',res.isFile())
}
pro(__dirname)
cmd效果图示
fs.readdir()
说明:读取目录中的子目录和文件,返回一个数组
方法演示
//导入fs、path模块
const fs = require('fs')
const path = require('path')
async function pro(url){
const res = await fs.promises.readdir(url)
console.log('读取到的子目录和文件:',res)
}
pro(__dirname)
cmd效果图示
fs.mkdir()
说明:创建一个自定义的目录
方法演示
//导入fs、path模块
const fs = require('fs')
const path = require('path')
const url = path.resolve(__dirname,'./data')
async function pro(_url){
await fs.promises.mkdir(_url)
//查看目录
const res = fs.promises.readdir(__dirname)
console.log('新增了一个目录:',res)
}
pro(url)
cmd运行效果
fs.exists()
说明:检测一个目录或者文件是否存在,返回布尔值,目前node还没有提供promise的写法,可以自己封装一个promise的写法
方法演示
//导入fs、path模块
const fs = require('fs')
const path = require('path')
const url = path.resolve(__dirname,'./abc.d')
//使用异步回调的写法
fs.exists(url,(data)=>console.log('检测结果为:',data))
cmd效果图示
封装fs.exists()方法的promise写法
说明:利用try{}catch(e){}对异常的捕获进行初步的判断一个文件的是否存在,然后再去对拿到的结果去处理
实现
//导入fs、path模块
const fs = require('fs')
const path = require('path')
// 初步判断给出反应
async function exists(dirname){
try{
await fs.promises.stat(dirname)
return true
}catch(e){
if(e.code == 'ENOENT') return false
throw e
}
}
async function pro(filename){
const flag = await exists(filename)
if(flag){
console.log('已存在:',filename)
}else{
await fs.promises.mkdir(filename)
console.log('新的目录已创建:',filename)
}
}
const url = path.resolve(__dirname,'./ab.cd')
pro(url)
cmd效果图示