Node.js知识点大全 最全笔记 知识点合集

第一章 绪论

第一讲.命令行窗口

命令行窗口也叫 小黑屏 cmd窗口 终端 shell

win+r,cmd,回车

常用指令:

  1. dir 列出当前目录下的所有文件
  2. cd+目录名 进入文件夹
  3. md+目录名 创建一个文件夹
  4. rd+目录名 删除一个文件夹
  5. 直接输入文件名+回车 打开文件
  6. e: 进入e盘

’ + '表示一个空格

目录:

  1. . 表示当前目录
  2. … 表示上一级目录
cd ..    回到上一级目录

环境变量(window系统中的变量)

分为用户变量和系统变量

path变量:存放的是在cmd命令行中可以直接打开的文件

当我们在命令行窗口打开一个文件或调用一个程序时,系统会先在当前目录下寻找文件程序,如果找到了,就直接打开,如果没找到,则会依次到环境变量的path中寻找,直到找到为止

如果没找到,则报错

所以我们可以将一些经常访问的程序和文件添加到path中,这样我们就可以在任意位置访问这些文件和程序.

修改之后要重启命令行才能生效

第二讲.进程和线程

进程:

进程负责为程序的运行提供必备的环境

进程就相当于工厂中的车间

线程:

是计算机中最小的计算单位,负责执行进程中的程序

线程相当于工厂中的工人

单线程是一个人干活,多线程是多个人干活

js是单线程

第三讲.Node历史

Node.js是一个能够在服务器端运行JS的开源代码,跨平台的JS运行环境

Node采用谷歌的V8引擎运行js代码,使用事件驱动,非阻塞和异步IO等技术提高性能,可优化应用程序的传输量和规模

Node.js创建起初的目的是创建高性能的web服务器

传统服务器是多线程的,每进来一个请求,就创建一个线程去处理请求

Node处理请求时是单线程的,但是在后台拥有一个IO线程池

第二章 Node.js基础

第一讲.操作JS

node书写js代码步骤:

  1. 安装node.js
  2. 打开cmd命令行
  3. 输入node,进入node状态,即可编写js代码

但是这样体验不是很好,我们更希望直接在.js文件中书写,然后用node执行

步骤:

  1. 打开cmd命令行
  2. 打开js所在文件夹
  3. 输入node+js文件名,即可执行

直接在目录中输入cmd,可以直接进入该目录所在的cmd

第二讲.模块化简介

JS的缺陷:

  1. 没有模块系统
  2. 标准库较少
  3. 没有标准接口
  4. 缺乏管理系统

模块化可以将一个完整的程序分成一个一个小的程序

降低耦合性,便于代码复用

如果程序设计的规模达到了一定程度

模块化可以有多种形式,但至少应该提供能够将代码分割为多个源文件的机制

CommonJS的模块功能可以帮我们解决这个问题,则必须对其进行模块化

CommonJS对模块的定义十分简单:

  1. 模块定义
  2. 模块引用
  3. 模块标识

模块化:

  1. 在node中,一个js文件就是一个模块

  2. 在node中,每一个js文件中的js代码,都是独立运行在一个函数中,而非全局作用域

    因此,一个模块中的变量和函数在其他模块中无法访问

通过require( )函数来引入外部的模块

可以传递一个文件的路径作为参数,node将会自动根据该路径来引入外部模块

这里的路径如果使用相对路径,必须使用.或…开头

使用require引入模块,该函数会return一个对象,该对象代表的是引入的模块

var md=require('./02.module.js');

由于每个js文件都是封闭的,因此如果想向外部暴露变量和方法,可以将需要暴露给外部的变量和方法,设置为exports的属性:

exports.x=10;
exports.fn=function(){
    console.log('a');
}

就不用var了

在引用时,这么写:

var a=require('./module01');
console.log(a.fn());

第三讲.模块化详解

模块标识:

require中的文件路径,称为模块标识

我们使用require引入外部模块时,使用的就是模块标识,我们可以通过模块标识来找到指定的模块

模块分为两类:

  1. 核心模块

    由node引擎提供的模块,核心模块的标识就是模块的名字

    var fs=require('fs');
    
  2. 文件模块

    用户自己创建的模块,模块标识就是文件路径,可以说绝对或者相对路径

    相对路径使用.或…开头

在全局对象有一个global,他的作用和网页中的window类似

在全局中创建的变量都会作为global的属性保存

在全局中创建的函数都会作为global的方法保存

可以通过global判断一个变量是不是全局变量

实际上模块中的代码都是包装在一个函数中执行的,并且在函数执行时,同时传递了五个实参

当node在执行模块中的代码时,它会首先在代码的最顶部添加如下代码:

function(exports,require,module,_filename,_dirname){

在代码的最底部,添加如下代码:

}//就是一个大括号

所以,我们可以使用exports和require

  1. exports 用来将变量或函数暴露到外部

  2. require 函数,用来引入外部的模块

  3. module 代表的是当前模块自身

    exports就是module的属性,所以既可以使用exports导出,也可以使用module.exports导出

  4. _filename 当前模块的完整路径

  5. _dirname 当前模块所在文件夹的完整路径

第四讲.exports和module.exports

我们不论使用exports还是module.exports,最后改变的都是module的exports属性

但是如果这样赋值:

exports={
    a:10;
    b:20;
}
module.exports={
    a:10;
    b:20;
}

第一个不能用,第二个可以用,因为exports是引用数据类型,它实质上是一个指针,如果直接修改exports,相当于将它指向了一个其他的对象.而修改module.exports,则是直接修改值本身

第五讲.包

CommonJS的包规范允许我们将一组相关的模块组合到一起,形成一组完整的工具

包规范:

  1. 包结构

    用于组织包的各种文件

  2. 包描述文件

    描述包的相关信息,以供外部读取分析

包实际上就是一个压缩文件,解压以后还原为目录.

符合规范的目录,除了主js文件以外,应该包含如下文件:

  1. package.json 描述文件,相当于包的说明书,必须有
  2. bin 可执行二进制文件
  3. lib js代码
  4. doc 文档
  5. test 单元测试

后面四个都是可有可无的

package.json,实质上就是一个json文件,用于描述非代码的相关信息

它是一个JSON格式的文件,其中的字段主要有:

  1. dependencies 依赖

    这个包使用时依赖于哪些包

  2. devDependencies 开发依赖

    开发时需要依赖什么,但是使用时并不需要

  3. main 主文件目录

  4. maintainers 开发者

  5. version 版本

  6. keywords 关键字

  7. bugs 提交bugs的地址

在JSON中,不能写注释!!!

第六讲.npm

NPM: Node Package Manager Node包管理系统

类似于360安全卫士里的软件管家

对于Node而言,NPM帮助其完成了第三方模块的发布,安装和依赖(会自动下载所有依赖的文件).借助NPM,Node与第三方模块之间形成了很好的生态系统

Node中最重要的功能就是NPM

NPM的使用:(要先在命令行中输入npm)

  1. npm±v 查看版本

  2. npm 帮助说明

  3. npm+search+包名 在网上搜索期望的包

  4. npm+install+包名 在当前目录安装包

    如果后面加一个–save 在安装包的同时加入到依赖中

  5. npm+install+包名±g 全局模式安装包,一般都是些工具,适用于计算机,而非项目.

  6. npm+init 在当前目录下创建.json文件(一路回车)

  7. npm+remove+包名 删除包

  8. npm+install 下载当前项目依赖的包,这是每一个包使用之前的必须指令!!!

第七讲.配置cnpm

npm是外网的,有时候不稳定

于是中国有一个镜像,将美国的东西都下载下来了

输入:

npm install -g cnpm -registry=https://registry.npm.taobao.org

然后以后使用的就是cnpm,而非npm去下载包

cnpm的文件格式与npm略有不同,目的是不会覆盖npm的官方版本

第八讲.搜索包的流程

通过npm下载的包,都放到了node_modules文件夹中

我们通过npm下载的包,直接通过包名引入即可

node在使用模块的名字引入模块时,会首先在当前目录的node_modules中寻找是否有该模块

如果有就直接用,如果没有则去上一个目录的node_modules中寻找

一直找到磁盘的根目录,如果一直没有则报错

第三章 文件系统

第一讲.Buffer缓冲区

从结构上看buffer很像一个数组,操作的方法也和数组类似.

数组中不能存储二进制数据,但是buffer可以,它的元素为16进制的两位数

使用buffer不需要引入模块,直接使用即可

var str="hello";
var buf=buffer.from(str);//将字符串内容转换成十六进制存储

buffer中的每一个元素的范围都是00-ff,实际上一个元素就表示内存中的一个字节

8bit=1byte

一个汉字占2个长度单位,3个字节空间

buffer中的内存不是通过JS分配的,而是直接在底层通过C++来创建的

也就是我们可以直接通过buffer来创建内存中的空间

以前创建指定大小的buffer:

var buf=new Buffer(10);//创建10字节大小的buffer

buffer的所有构造函数都不推荐我们使用,已经过期(上面那个不能用了)

现在创建buffer:

var buf=Buffer.alloc(10);
buf[0]=0xaa;//添加一个十六进制字符
buf[1]=88;//添加一个十进制字符
buf[10]=0xff;//会被忽略
buf[6]=556;//溢出了,只取后8位

Buffer的大小一旦确定,永远不能修改,Buffer是对底层内存的直接操控,其中的空间是连续的

如果下标越界,越界的部分会被忽略

只要Buffer中的数字在控制台或页面中输出,都会自动转换成十进制

如果想输出原有内容出来,可以将其转换为字符串:

console.log(buf[1].toString(16));//16指的是以16进制输出

当使用Buffer.alloc( )时,使用内存空间之前,会将内存中的内容全部清空

但是如果使用Buffer.allocUnsafe( ),就不会清空其中的内容,因此buffer中可能会有敏感数据

但是Unsafe方法的性能会更好一些

buf.toString( )方法可以将缓冲区中的内容直接转换成字符串

第二讲.文件系统简介

文件系统(File System,简称fs),通过node操作系统文件

在Node中,与文件系统的交互是非常重要的,服务器的本质就是将本地的文件发送给远程的服务端

Node通过fs模块和文件系统进行交互

该模块中提供了一些标准文件来打开,读取,写入文件,以及与其交互

使用fs需要先引fs模块,直接引入不需要下载:

var fs=require('fs');

fs模块中所有方法都有两种形式可以选择: 同步和异步

同步文件系统会阻塞程序的执行,也就是除非操作完毕,否则不会向下执行代码

异步文件不会阻塞程序的执行,而是在操作完成时,通过回调函数将结果返回

异步方法都有回调函数,同步方法都有返回值

第三讲.同步文件写入

手动写入文件的步骤:

  1. 打开文件
  2. 向文件中写入内容
  3. 保存并关闭文件

同步文件的写入:

  1. 打开文件

    三个参数:

    • path : 要打开文件的路径
    • flags : 打开文件要做的操作类型(读还是写) r 只读 w 可写
    • mode : 设置文件的操作权限,一般不传

    会返回一个描述符(文件编号)作为结果,我们可以对该描述符进行各种操作

    var fd=fs.openSync('hello.txt','w');
    
  2. 向文件中写入内容

    参数:

    • fd : 要写入的文件的描述符
    • string : 要写入的内容
    • position : 文件写入的起始位置(一般不传)
    fs.writeSync(fd,'今天天气真不错');
    
  3. 保存并关闭文件

    在服务器中,程序不会停止,因此文件需要单独手动关闭

    参数: fd 要关闭的文件的描述符

    fs.closeSync(fd);
    

第四讲.异步文件写入

异步方法没有返回值,由回调函数的参数返回

回调函数有两个参数:

  1. err : 错误对象,如果没有错误则为null

    如果使用只读打开文件,但是又没有创建文件,就会报错

  2. fd : 文件的描述符

异步写入的特点是不阻塞其他进程,当文件读取以后,接下来的操作会交给线程池来进行,由线程池判断谁先谁后

因此,open下面的代码可能会先于open的回调函数执行.

因此,对文件的写入操作应该写在回调函数中

异步文件写入步骤:

  1. 引入fs模块

    var fs=require("fs")
    
  2. 打开文件

    方法 : fs.open( )

    参数:

    • path : 文件路径
    • flags : 操作标志
    • mode : 通常省略
    • callback : 回调函数 不能省略
    fs.open('hello.txt','w',function(err,fd){
        if(!err){
            console.log(fd);
        }else{
            console.log(err);
    })
    
  3. 写入内容

    方法 : fs.write( )

    参数:

    • fd : 文件描述符

    • text : 写入的内容

    • callback : 回调函数

      参数只有一个,就是err

    fs.open('hello.txt','w',function(err,fd){
        if(!err){
            fs.write(fd,'今天天气真不错',function(err){
                if(!err) console.log('写入成功');
            })
        }
    })
    
  4. 保存并关闭文件

    只要回调函数中的内容完成之后,就可以关闭文件

    方法 : fs.close( )

    参数: fd callback

    回调函数的参数同样只有err

    fs.open('hello.txt','w',function(err,fd){
        if(!err){
            fs.write(fd,'今天天气真不错',function(err){
                if(!err) console.log('写入成功');
            })
        }
        fs.close(fd,function(err){});
    })
    

异步的优点:

程序会继续执行,不必等待系统响应

但是同步更符合人类思维,便于编程

而异步不符合人类函数,代码可读性差,但是有性能优势

异步可以处理异常,而同步不能处理异常

第五讲.简单文件写入

不论是同步还是异步,都比较麻烦,在实际开发中用的不多

也分简单同步和简单异步

简单同步 : fs.writeFileSync(file,data,[option]);

简单异步 : fs.writeFile(file,data,[option],callback);

参数:

  • file : 要操作的文件路径

  • data : 要写入的数据

  • option : 写入的设置,可选参数,一般不写

    以对象形式传入,可选参数有 : 编码形式,mode,操作权限

    {
        flag:'a';
    }
    
  • callback : 回调函数

    回调函数的参数 : err

写入步骤:以异步为例

  1. 引入fs模块

    var fs=require('fs');
    
  2. 写入

    fs.writeFile('hello.txt','今天天气真不戳',function(err){
        if(!err) console.log('写入成功');
    })
    

    它会自动打开和关闭

文件写入时,默认是从头开始写,会覆盖曾经写过的内容

如果不想从头写,要将flags写成 a ,意为追加

之前写的是相对路径,但是也可以写绝对路径,不过由于’\'是转义字符,因此要写双斜杠代替斜杠才能表示路径:

fs.writeFile("C:\\User\\Desktop\\hello.txt",'今天天气真不戳',{flag:'a'},function(err){
    if(!err) console.log('写入成功');
})

或者,不写\,而是写/,可以只写一个,也可以达到相同的效果

第六讲.流式文件写入

之前写入文件的方式,都是已经准备好了所有要写的内容,然后一次性写入

因此必须在写之前准备好所有文件,这样会存在一个问题,如果文件过大,会导致占用过多的内存空间

因此,前面所有的文件写入,都不适合大文件的写入,性能较差,且容易导致内存溢出

由此引入了流式文件写入,相当于在文件上通了一根水管,源源不断的将文件送进去,而不是一次性写入

步骤:

  1. 打开文件

    var fs=require('fs');
    
  2. 创建一个可写流(就是一个水管)

    方法 : fs.createWriteStream(path,[option])

    参数 : 写入文件的路径,写入设置

    var ws=fs.createWriteStream('hello.txt');
    

    这样ws就相当于一根水管,hello.txt就相当于一个水池,二者成功连接上

  3. 像文件中输出内容

    方法 : ws.write( )

    参数 : 字符串

    ws.write('今天天气真不戳');
    

它的特点是只要ws还在,想什么时候写就什么时候写.

但是目前还没有关闭,可能对性能有所损伤

可以通过监听流的open和close事件来监听流的打开和关闭

监听方法 : ws.once( )

ws.on( ) 和 ws.once( )都可以绑定一个事件,不同的是on绑定的是长期有效的事件,而once绑定的是一次性事件

on是事件每次触发都会执行方法,once是只有第一次触发会执行方法

由于open只会出现一次,所以这里用once比较好

参数:

  1. 要监听的事件
  2. 回调函数
ws.once('open',function(){
    console.log('流打开了');
})

流式写入是异步写入,在关闭流时,不能从接受端断开,因为还会有内容在流中没有传输完成,因此不能使用ws.colse( )方法

但是可以从发送端断开,这样流中的文件可以正常传输

从发送端断开的方法 : ws.end( )

ws.end();

第七讲.简单文件读取

文件的读取和写入类似,同样有同步文件读取,异步文件读取,这两个不再讲

另外就是简单文件读取和流式文件读取

简单文件读取方法 :

  1. 同步简单读取 : fs.readFileSync(path,[option])
  2. 异步简单读取 : fs.readFile(path,[option],callback)

参数:

  • path : 要读取文件的路径

  • potion : 要读取文件的设置

  • callback : 回调函数

    参数:

    • err : 异常
    • data : 读取到的数据,返回类型为Buffer,需要toString( )一下才能用

返回值是Buffer,目的是在读取图片,音频等非文本文件时,也可以正常读取,而不是出现乱码

步骤:

  1. 打开文件

    var fs=require('fs');
    
  2. 读取文件

    fs.readFile('hello.text',function(err,data){
        if(!err) console.log(data.toString());
    })
    

在读取数据之后,还可以再写出去

  1. 写入文件

    fs.readFile('an.jpg',function(err,data){
        if(!err){
        	fs.writeFile('hello.jpg',data,function(err){
                if(!err) console.log('文件写入成功');
            })
        }
    })
    

读取+写入,即可完成一个复制的功能.

第八讲.流式文件读取

与流式写入类似,同样适用于大文件,可以分多次读取到内存中

步骤 :

  1. 引入文件

    var fs=require('fs');
    
  2. 创建一个可读流

    方法 : fs.createReadStream(path,[option])

    参数 : 读取文件的路径,读取设置

    var rs=fs.createReadStream('an.jpg');
    
  3. 监听流的开启和关闭

    rs.once('open',function(){
        console.log('可读流打开了');
    })
    rs.once('close',function(){
        console.log('可读流关闭了');
    })
    

如果要读取一个可读流的数据,则必须为可读流绑定一个data事件,data事件绑定完毕,会自动开始读取数据

  1. 读取数据

    读取到的数据通过data参数接收

    rs.on('data',function(data){
        console.log(data);
    })
    

    会自动判断文件的大小,然后分次读取

    读完了会自动关闭,但是如果不读就不会关闭.

  2. 写入数据

    先监听可写流的开启和关闭.

    rs.on('data',function(data){
        ws.write(data);
    })
    rs.once('close',function(){
        console.log('可读流关闭了');
        ws.end();//在数据读取完成之后,可读流先关闭,然后才关闭可写流
    })
    

问题:要给读取和写入都设置监听,过于复杂

在rs中有一个方法 : rs.pipe(ws)

它可以将可读流中的方法直接写到可写流之中

当读写结束之后,会自动关闭,可以不用监听.

var fs=require('fs');
var rs=fs.createReadStream('an.jpg');
var ws=fs.createWriteStream('hello.jpg');
rs.pipe(ws);

第九讲.fs模块的其他方法

Sync表示同步,没有Sync则表示异步,每个方法只取一种进行说明

验证路径是否存在 : fs.existsSync(path,[option])

只有同步的可以用

var fs=require('fs');
var isExists=fs.existsSync('a.mp3');

返回值为true表示存在,false表示不存在

获取文件信息 : fs.stat(path,callback)

它会给我们返回一个对象stat,其中保存了当前对象状态的相关信息

stat对象中有以下内容:

  1. isFile( )方法 是否是文件
  2. isDirectory( )方法 是否是文件夹
  3. size属性 文件大小
  4. birthtime属性 文件的创建时间
var fs=require('fs');
fs.stat('a.mp3',function(err,stat){
    console.log(stat.size);
})

删除文件 : fs.unlink(path,callback)

fs.unlinkSync('hello.txt');

会将文件删除

列出文件 : fs.readdir(path,[option],callback)

读取一个目录的目录结构

回调函数两个参数:

  1. err 异常
  2. files 是一个字符串数组,每一个元素就是一个文件夹或文件的名字
fs.readdir('hello.txt',function(err,files){
    console.log(files);
})

截断文件 : fs.truncate(path,len,callback)

将文件修改为指定子节的大小

fs.truncateSync('hello.txt',9);

创建文件夹 : fs.mkdir(path,[mode],callback)

fs.mkdirSync('hello')

删除文件夹 : fs.rmdirSync(path)

fs.rmdirSync('hello');

重命名文件 : fs.rename(oldPath,newPath,callback)

参数:

  1. oldPath 旧的路径(名字)
  2. newPath 新的路径(名字)
  3. callback 回调函数
fs.rename('a.mp3','b.mp3',function(err){
    if(!err) console.log('修改成功');
})

不仅可以传递文件名,也可以传递一个新的路径,这样也可以实现文件的移动

监视文件的修改 : fs.watchFile(filename,[option],listener)

参数:

  1. filename : 要监视的文件的名字

  2. options : 配置选项

  3. listener : 回调函数,当文件发生变化时,回调函数会执行

    参数:

    • curr : 当前文件的状态
    • prev : 修改前文件的状态

    这两个对象都是stats对象,属性和可用方法与stats相同

fs.watchFile('hello.txt',function(curr,prev){
    console.log('修改前文件大小'+prev.size);
    console.log('修改后文件大小'+curr.size);
})

会一直监听着这个文件,只要文件发生了变化,回调函数就会执行

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值