Node.js(尚硅谷最经典Node.js快速入门学习笔记)

一、简介

  • Node.js是一个能够在服务器端运行JavaScript的开放源代码、跨平台JavaScript运行环境。
  • Node采用Google开发的V8引擎运行js代码,使用事件驱动、非阻塞和异步I/O模型(I:input、O:output)等技术来提高性能,可优化应用程序的传输量和规模。
  • Node大部分基本模块都用JavaScript编写。在Node出现之前,JS通常作为客户端程序设计语言使用,以JS写出的程序常在用户的浏览器上运行。
  • 目前,Node已被IBM、Microsoft、Yahoo!、Walmart、Groupon、SAP、LinkedIn、Rakuten、PayPal、Voxer和GoDaddy等企业采用。
  • 但是Node与其他语言最大的不同之处是:PHP等语言是阻塞的,而Node是非阻塞的。

Node是对ES标准的一种实现,Node也是JS引擎。

通过Node可以使JS代码在服务端执行。

Node的服务器是单线程的,但是在后台拥有一个I/O线程池。

Node处理速度快,适合页面渲染。

 二、Node的用途

 1、Web服务API,比如rest

 2、实时多人游戏

 3、后端的Web服务,例如跨域、服务器端的请求

 4、基于Web的应用

 5、多客户端的通信,如即时通信

三、使用Node执行js文件

1、使用Win+R打开命令行窗口

2、输入cd+目录名,进入文件所在目录

3、node + 空格 + 所需执行的js文件名

快捷方式:在所需执行文件的文件夹上方输入cmd,在执行第三步操作。

四、模块化介绍

1、ECMAScirpt标准的缺陷

  • 没有模块系统(引入jquery属于模块化,但不属于模块化系统,ES6有模块化)
  • 标准库较少
  • 没有标准接口
  • 缺乏管理系统

2、模块化

  • 如果程序设计的规模达到了一定程度,则必须对其进行模块化。
  • 模块化可以有多种形式,但至少应该提供能够将代码分割为多个源文件的机制。
  • CommonJS的模块功能可以帮我们解决该问题。、
  • 在Node中,一个js文件就是一个模块。
  • 在Node中,每一个js文件中的js代码都是独立运行在一个函数中的,而不是全局作用域,所以一个模块中的变量和函数在其他模块中无法访问。

CommonJS规范

  • CommonJS规范的提出,主要是为了弥补当前JavaScript没有标准的缺陷。
  • CommonJS规范为JS指定了一个美好的愿景,希望JS能够在任何地方运行。
  • CommonJS对模块的定义十分简单:模块引用、模块定义、模块标识。

3、模块引用

       在Node中,通过require()函数来引入外部的模块。

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

       这里路径如果使用相对路径,必须以.或者..开头。

require("./02.moudle.js");

      使用require()引入模块以后,该函数会返回一个对象,这个对象代表的是引入的模块。

可以通过exports来向外暴露变量和方法

只需要将需要暴露给外部的变量或方法设置为exports的属性即可。

<!--01.module.js--!>
console.log("我是一个模块,我是01.module");
exports.x = "我是01.module.js中的x";
exports.y = "我是01.module.js中的y";
exports.fn = function() {

};
<!--02.module.js--!>
var md = require("./01.module.js");
console.log(md.x);
console.log(md.y);
console.log(md.fn);

 

 引用案例:定义一个模块match,在该模块中提供两种方法:

                   add(a,b);求两个数的和,mul(a,b);求两个数的积

//02.module.js

var math = require("./03.math");
console.log(math.add(123, 456)); //579



//03.math.js
exports.add = function(a, b) {
    return a + b;
}
exports.mul = function(a, b) {
    return a * b;
}

4、模块定义

  • 在运行环境中,提供了exports对象用于导出当前模块的方法或者变量,并且它是唯一的导出的出口。
  • 在模块中还存在一个module对象,它代表模块自身,而exports是module的属性。
  • 在Node中一个文件就是一个模块。

在Node中,模块分为三类:

      ① 内建模块:底层由C++编写的模块

      ② 核心模块:由Node引擎提供的模块

                             核心模块的标识就是模块的名字

                 示例:var fs = require("fs");

      ③ 文件模块:由用户自己创建的模块

                            文件模块的标识就是文件的路径

                         (绝对路径,一般来说是相对路径。相对   路径使用.或者..开头)

5、模块标识

  •  模块标识其实就是模块的名字,也就是传递给require()方法的参数,它必须是符合驼峰命名法的字符串,或者是以.、…开头的相对路径、或者绝对路径。
  • 使用require()引入外部模块时,使用的就是模块标识。我们可以通过模块标识来找到指定的模块。

6、Node的模块实现

  • Node中虽然使用的是CommonJS规范,但是其自身也对规范做了一些取舍。
  • 在Node中引入模块,需要经历如下三个步骤:

        —路径分析

        —文件定位

       —编译执行

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

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

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

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

      function(exports,require,module,__filename,__dirname){

  • 在代码的最底部,添加如下代码: }
  • 实际上模块中的代码都是包装在一个函数中执行的,并且在函数执行时,同时传递进了5个实参。

         ① exports:该对象用来将变量或函数暴露到外部

         ② require:函数,用来引入外部模块

         ③ module:module代表的当前模块本身,exports是module的属性

                             既可以使用exports导出,也可以使用module.exports导出

         ④ __filename:当前模块的完整路径

         ⑤ __dirname:当前模块所在文件夹完整路径

     

exports和module.exports:

    ① 通过exports只能使用.的方式来向外暴露内部变量

         exports.xxx = xxx

    ② 而module.exports既可以通过.的方式,也可以直接赋值

         module.exports.xxx = xxxx

         module.exports = { }

五、包 package

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

CommonJS的包规范由包结构和包描述文件两个部分组成。

1、包结构

  • 用于组织包中的各种文件
  • 包实际上就是一个压缩文件,解压以后还原为目录。复合规范的目录,应该包含如下文件:

        —package.json:描述文件

        —bin:可执行二进制文件

        —lib:js代码

        —doc:文档

        —test:单元测试

2、包描述文件

  • 描述包的相关信息,以供外部读取分析。
  • 包描述文件用于表达非代码相关的信息,它是一个JSON格式的文件:package.json,位于包的根目录下,是包的重要组成部分。
  • package.json中的字段:

       name、description、version、keywords、maintainers、contributors、bugs、licenses、

       repositories、dependencies、homepage、os、cpu、engine、builtin、direcotries、

       implements、scripts、author、bin、main、devDependencies。

六、NPM(Node Package Manager)

  • CommonJS包规范是理论,NPM是其中一种实践。
  • 对于Node而言,NPM帮助其完成了第三方模块的发布、安装和依赖等。借助NPM,Node与第三方模块之间形成了很好的一个生态系统。
  • 通过NPM下载的包都放到node_modules文件夹中
  • 通过NPM下载的包,直接通过包名引入即可。
  • Node在使用模块名字来引入模块时,首先在当前目录的node_modules中寻找是否含有该模块:

       ① 如果有则直接使用,如果没有则去上一级目录的node_modules中寻找

       ② 如果有则直接使用,如果没有则再去上一级目录寻找,直到找到为止

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

1、NPM命令(cmd)

① npm -v :查看版本

② npm:帮助说明

③ npm version:查看所有模块的版本

④  npm search  包名:搜索模块包

⑤  npm install / i 包名:在当前目录安装包

⑥  npm install  包名 + -g:全局模式安装包(全局安装的包一般都是一些工具)

⑦ npm remove 包名:删除包

npm install 包名 --save:安装包并添加到依赖中

npm install :下载当前项目所依赖的包

⑩ npm install 文件路径:从本地安装

     npm install 包名 -registry=地址:从镜像源安装

     npm config set registry 地址:设置镜像源

七、Buffer(缓冲区)

从结构上看Buffer非常像一个数组,它的元素为16进制的两位数。

数组中不能存储二进制的文件,而buffer就专门用来存储二进制数据。

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

实际上一个元素就表示内存中的一个字节。

实际上Buffer中的内存不是通过JavaScript分配的,而是在底层通过C++申请的。

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

1、Buffer操作

(1)将一个字符串保存到buffer中

var str = "hello world";
//将一个字符串保存到buffer中
var buf = Buffer.from(str);

console.log(buf);         //<Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>
console.log(buf.length);  //11    占用内存的大小    表示占用内存11个字节
console.log(str.length);  //11    获取的是字符串的长度

Buffer中存储的都是二进制数据,但是是以十六进制的形式来显示。

buffer中的每一个元素的范围是从00—ff (00000000—11111111)

计算机中,一个0或者一个1,称为1位(bit)

8bit = 1byte(字节),字节是数据传输最小的单位

buffer中的一个元素,占用内存一个字节。

英文占用内存中的一个字节,汉字占用内存三个字节

  • 1024byte = 1kb
  • 1024kb = 1mb
  • 1024mb=1gb
  • 1024gb=1tb

(2)创建一个指定大小的buffer

//buffer的构造函数都是不推荐使用的
var buf2 = new Buffer(10); //10个字节的buffer
console.log(buf2.length);

Buffer的大小一旦确定,则不能修改。

Buffer实际上是对底层内存的直接操作。

//创建一个10字节的buffer
var buf2 = Buffer.alloc(10);
buf2[0] = 88;
buf2[1] = 255;
buf2[2] = 0xaa;
buf2[10] = 15;
console.log(buf2);     //<Buffer 58 ff aa 00 00 00 00 00 00 00>

//只要数字在控制台或页面中输出一定是10进制
console.log(buf2[2]);  //170
console.log(buf2[2].toString(16));     //aa 

Buffer.allocUnsafe(size)  创建一个指定大小的buffer,但是buffer中可能含有敏感数据.

var buf3 = Buffer.allocUnsafe(10);
console.log(buf3);    //

Buffer.from(str):将一个字符串转化为buffer

Buffer.alloc(size):创建一个指定大小的buffer

Buffer.allocUnsafe(size):创建一个指定大小的buffer

buf.toString():将缓冲区的数据转化为字符串

var buf4 = Buffer.from("我是一段文本数据");
console.log(buf4.toString());

 八、fs(文件系统)

文件系统(File System):通过Node来操作系统中的文件。

使用文件系统,需要先引入fs模块,fs是核心模块,直接引入,不需要下载。

  • 在Node中,与文件系统的交互是非常重要的,服务器的本质就将本地的文件发送给远程的客户端。
  • Node通过fs模块来和文件系统进行交互。
  • 该模块提供了一些标准文件访问API来打开、读取、写入文件,以及与其交互。
  • 要使用fs模块,首先需要对其进行加载。
    const fs = require("fs");

1、同步调用

fs模块中所有的操作都有两种形式可供选择同步和异步。

  • 同步文件系统会阻塞程序的执行,也就是除非操作完毕,否则不会向下执行代码。
  • 异步文件系统不会阻塞程序的执行,而是在操作完成时,通过回调函数将结果返回。

(1)打开文件

fs.openSync*(path,flags[, mode])

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

(2)向文件中写入内容

fs.writeSync(fd,string[,position[,encoding]])

  • fd:文件的描述符,传递要写入文件的描述符
  • string:要写入的内容
  • position:写入的起始位置
  • encoding:写入的编码,默认utf-8

(3)保存并关闭文件

fs.closeSync(fd)

  • fd:要关闭的文件的描述符
var fs = require("fs");
//1、打开文件
var fd = fs.openSync("hello.txt","w");
//2、向文件中写入内容
fd.writeSync(fd,"今天晚上吃什么呢???",2);
//3、保存并关闭文件
fd.closeSync(fd);

2、异步调用

(1)打开文件

fs.open(path, flags[, mode], callback) 

  • callback:不能省略,是回调函数
  • 用来打开一个文件
  • 异步调用的方法,结果都是通过回调函数的参数返回的。
  • 回调函数有两个参数:

        ① err  错误对象:如果没有错误则为null

        ② fd 文件的描述

(2)向文件中写入内容

fs.write(fd,string[,position[,encoding]],callback)

  • 用来异步写入一个文件

(3)保存并关闭文件

fs.close(fd,callback)

  • 用来关闭文件的
  • 异步的close(2)。完成回调只有一个可能的异常参数
/*异步文件写入*/
// (1)打开文件
//fs.open(path, flags[, mode], callback)
var fs = require("fs");
//异步调用的方法,结果都是通过回调函数的参数返回的
fs.open("hello2.txt", "w", function(err, fd) {
    //判断是否出错
    if (!err) {
        //如果没有出错,则对文件进行写入操作
        // (2)向文件中写入内容
        fs.write(fd, "这是异步写入的内容", function(err) {
            if (!err) {
                console.log("写入成功~~~");
            }
            //(3)保存并关闭文件
            fs.close(fd, function(err) {
                if (!err) {
                    console.log("文件已关闭~~~");
                }
            })
        });

    } else {
        console.log(err);
    }
})

3、简单文件

(1)写入

同步:fs.writeFileSync(file,data[,options],callback)

异步:fs.writeFile(file,data[,options])

  • file:要操作的文件路径
  • data:要写入的数据
  • option:选项,可以对写入进行设置(可省略)
  • callback:写入完成以后执行的函数
  • flag: r(只读)   w(可写)  a(追加)

 


var fs = require("fs");
//此时的hellow3.txt是相对路径
fs.writeFile("hello3.txt", "这是通过writeFile写入的内容", { flag: "a" }, function(err) {
    if (!err) {
        console.log("写入成功");
    } else {
        console.log(err);
    }
});


//绝对路径的使用
使用前:C:\Users\lilichao\Desktop\hello.txt
使用后:C:\\Users\\lilichao\\Desktop\\hello.txt

 (2)文件读取

同步:fs.readFile(path[,options],callback)

异步:fs.readFile(path[,options])

  •   path:要读取文件的路径
  •   options:读取的选项
  •   callback回调函数:通过回调函数将读取到的内容返回(err,data)
  •   err:错误对象
  •   data:读取到的数据,会返回一个Buffer,可转换成字符串
//简单文件读取
var fs = require("fs");
fs.readFile("hello3.txt", function(err, data) {
    if (!err) {
        // console.log(data);
        // 将data写入到文件中
        fs.writeFile("hello.jpg", data, function(err) {
            if (!err) {
                console.log("文件写入成功");
            }
        })

    }
})

4、流式文件

同步、异步、简单文件的写入都不适合大文件的写入,性能较差,容易导致内存溢出。

往一个文件中写入大量数据时,最好的方法之一是使用流。

(1)写入

流式文件可持续写入。

fs.createWriteStream(path[, options])   可以用来创建一个可写流

  • path:文件路径

  • options:配置的参数,可省略不写

var fs = require("fs");
var ws = fs.createWriteStream("hello4.txt");
//可以通过监听流的open的close事件来监听流的打开和关闭

//打开流
//open只会触发一次,是一次性事件
//on(事件字符串,回调函数) :可以为对象绑定一个事件
//once(事件字符串,回调函数):可以为对象绑定一个一次性的事件,该事件将会在触发一次以后自动失效

ws.once("open", function() {
    console.log("流打开了~~~");
});
ws.once("close", function() {
    console.log("流关闭了~~~");
})

//通过ws向文件中输入内容,可持续写入
ws.write("通过可写流,写入文件的内容");
ws.write("今天晚上吃什么?");
ws.write("甜皮鸭");
ws.write("稀饭");

//关闭流
ws.close();

(2)文件读取

流式文件的读取也使用于一些比较大的文件,可以分多次将文件读取到内存中。

/流式文件读取
// 流式文件的读取也使用于一些比较大的文件,可以分多次将文件读取到内存中
var fs = require("fs");
//创建一个可读流
var rs = fs.createReadStream("E:/前端软件/学习操作/8.Node.js/03-文件系统/草东-还愿.mp3");

//创建一个可写流
var ws = fs.createWriteStream("a.mp3");
//监听流的开启和关闭
rs.once("open", function() {
    console.log("可读流打开了~~");
});
rs.once("close", function() {
    console.log("可读流关闭了~~~");
    //数据读取完毕,关闭可写流
    ws.close();
});

ws.once("open", function() {
    console.log("可写流打开了~~~");
});
ws.once("close", function() {
    console.log("可写流关闭了~~~");
})

//如果要读取一个可读流中的数据,必须要为可读流绑定一个data事件,data事件绑定完毕,它会自动开始读取数据
rs.on("data", function(data) {
    //console.log(data);
    //将读取到的数据,写入到可写流中
    ws.write(data);
});

 pipe()可以将可读流中的内容,直接输出到可写流中。

var fs = require("fs");

//创建一个可读流
var rs = fs.createReadStream("E:/前端软件/学习操作/8.Node.js/03-文件系统/草东-还愿.mp3");
//创建一个可写流
var ws = fs.createWriteStream("b.mp3");

//pipe()可以将可读流中的内容,直接输出到可写流中
rs.pipe(ws);

九、其他操作

1、验证路径是否存在:fs.existsSync(path)

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

                               fs.statSync(path)

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

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

                       fs .unlinkSync(path)

4、列出文件:fs.readdir(path,[,options],callback)

                        fs.readdirSync(path,[,options])

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

                       fs.truncateSync(path,len)

                       将文件修改为指定的大小

6、建立目录:fs.mkdir(path,[,mode],callback)

                       fs.mkdirSync(path,[,mode])

7、对文件进行重命名:fs.rename(oldPath,newPath,callback)

                                      fs.renameSync(oldPath,newPath)

                                      参数:oldPath:旧的路径

                                                newPath:新的路径

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

                                  参数:filename:要监视的文件的名字

                                             options:配置选项

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

var fs = require("fs");
//一、检查一个文件是否存在
// fs.existsSync(path)
var isExists = fs.existsSync("a.mp3");
console.log(isExists);


//二、获取文件的状态:fs.stat(path,callback)

// fs.statSync(path)

fs.stat("a.mp3", function(err, stat) {
    //size:文件的大小
    //isFile():是否是一个文件
    //isDirectory():是否是一个文件夹
    console.log(stat.size);
})

//三、删除文件:fs.unlink(path,callback)
//   fs.unlinkSync(path)
fs.unlinkSync("a.mp3");


//四、列出文件  fs.readdir(path,[,options],callback)
// fs.readdirSync(path,[,options])
// 读取一个目录的目录结构
//files是一个字符串的数组,每一个元素就是一个文件夹,或文件的名字

fs.readdir(".", function(err, files) {
    if (!err) {
        console.log(files);
    }
});

//五、截断文件 fs.truncate(path,len,callback)
// fs.truncateSync(path,len)
// 将文件修改为指定的大小
fs.truncateSync("hello2.txt", 14);



//六、建立目录
// fs.mkdir(path,[,mode],callback)
// fs.mkdirSync(path,[,mode])
fs.mkdirSync("abc");




//七、对文件进行重命名:fs.rename(oldPath,newPath,callback)
// fs.renameSync(oldPath,newPath)
// 参数:oldPath:旧的路径
//       newPath:新的路径
fs.rename("hello.txt", "笔记本.txt", function(err) {
    console.log("修改成功");
});



// 八、监视文件的修改:fs.watchFile(filename[,options],listener)
// 参数:filename:要监视的文件的名字
//            options:配置选项
//            listener:回调函数,当文件发送变化时,回调函数会执行
//   在回调函数中会有两个参数:cur 当前文件的状态
//                           prev 修改前文件的状态
//                           这两个对象都是stats对象


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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值