看完我的笔记不懂也会懂----Node.js
- Node.js 学习
- 命令行窗口
- 进程与线程
- ECMAScript的缺点
- Node模块化
- Node中的全局对象
- 包 package
- NPM包管理器 (Node Package Manager)
- package.json参数详解
- Buffer 缓冲区
- fs(file system) 文件系统
- 文件写入
- 文件读取
- 其他方法
Node.js 学习
命令行窗口
- 什么命令行窗口?
- 使用快捷键win+R后,输入cmd后,运行所弹出的黑色窗口
- 命令行窗口的别名?
- shell 终端 CMD窗口
- 常用命令
dir: 列出当前目录下的所有文件 cd 目录名: 转到目标目录 cd .: 去当前目录 cd ..: 去上级目录 md 文件夹名称: 创建一个文件夹 rd 文件夹名称: 删除指定文件夹(如果文件夹中有文件不会删除) rd /S 文件夹名称: 删除指定文件夹(删除文件夹不管其中是否有文件) 文件名: 打开指定文件 (当我们使用cmd打开一个文件或者调用一个程序的时候, 系统会首先在当前目录下寻找, 如果没有就会到Path中寻找, 还没找到就会报错)
- 环境变量(windows系统中的变量)
- Path变量: 保存了许多的路径
- 通过往Path中添加路径,可以在cmd中直接运行文件而不用输入路径
- 所以,我们可以将一些经常需要访问的程序或文件的路径添加到环境路径中,以便于在cmd可以直接打开
进程与线程
- 进程
- 进程负责为程序运行提供必备的环境
- 进程就好比工厂的车间
- 线程
- 线程负责执行程序
- 线程相当于工厂车间中的工人
- 线程之间可以互相通信/共享内存空间
- 如果内存空间有线程数量读写的限制:
- 当只能让一个线程读写时,其他的线程必须要等待,这时需要互斥锁
- 当只能让一定数量的线程读写时,多余的线程必须等待,这时需要信号量
- 线程可以分为单线程与多线程
ECMAScript的缺点
- 没有模块化系统
- 标准库较少
- 没有标准接口
- 缺乏管理系统
Node模块化
-
在Node中,一个js文件就是一个模块
-
模块分为核心模块(Node提供的)与文件模块(用户自己编写的)
-
如何引入模块
- 使用require("模块路径") 注意:模块路径如果是相对路径必须在开头添加./或../
-
默认下,每个模块都是独立的(闭包),这意味着当前模块中无法访问到其他模块的变量与函数(作用域),如果模块需要访问别的模块中的变量或方法,就需要将这些变量或方法向外暴露
//02-module1 // 这个将作为一个模块被02-module2 引用 //向外暴露变量 其他模块可以看见 exports.a = 666; //使用exports.变量名向外(别的模块)暴露 //02-module2 // node使用require("模块路径") //使用require()引入模块以后,会返回一个对象,这个对象包含引入模块中的所有变量、函数 var module02 = require("./02 Node module.js"); //引入模块 console.log(module02); //{ a: 666 } console.log(module02.a); //666
-
证明文件模块是在一个函数内
//证明模块就是一个函数 var a = 666; //方式一: 函数外部是全局作用域global,如果此时定义的a在global中无法看到说明现在位于函数中 console.log(global.a); //undefined //方式二: 利用 不用声明符声明会变为全局变量的原理 反证位于函数中 b = 'i am in global !'; console.log(global.b); //'i am in global !' //方式三: 利用 arguments 只有在函数中才有的特性 console.log(arguments); //方式四: 利用arguments.callee查看当前函数 console.log(arguments.callee) //function //方式五(最终方式): 直接能够查看整个函数 console.log(arguments.callee.toString())
//当执行模块中的代码时候,会将代码包装在一个函数中运行,同时传进5个参数 function (exports, require, module, __filename, __dirname){ 你的代码 exports : 该对象是 module对象的属性 用于储存 暴露在外部(全局global)的属性与方法 require : 该对象储存这该模块的一些信息 module: 该对象储存这模块的详细信息,其中就有exports __filename: 值是这个模块的详细路径 __dirname: 值是这个模块所在的文件路径 }
-
关于exports与module.exports
exports、module.exports作用是:能够像外暴露属性与方法(别忘记了模块是在一个函数中的,所以在其中定义的变量与方法都是属于局部作用域的)
//exports与module.exports指向的是同一个对象 console.log(exports === module.exports) //true //可以给module.exports直接赋值一个新的对象,用于一次性向外暴露多个变量或方法 module.exports = { name: 'Fitz', gender: 'Male', address: 'Dongguan' } console.log(arguments[2].exports) //{ name: 'Fitz', gender: 'Male', address: 'Dongguan' } //但是不能给exports直接赋值新的对象,来达到一次性暴露多个属性与方法的目的 exports = { name: 'dada' } //在别的模块中可以看到exports并没有改变 console.log(arguments[2].exports) //{ name: 'Fitz', gender: 'Male', address: 'Dongguan' } //原因 //module.exports与exports的关系应该是这样的: var module_exports = {} //module.exports指向一个对象 var exports = module.exports //exports与module.exports绑定同一个对象 //如果修改的是module.exports var module.exports = new Object(); //exports的引用也随之发生改变 //但是如果修改的是exports就等于 var exports = new Object(); //此时module.exports 与 exports引用的是两个不同的对象 //而由于真正向外暴露的对象是module.exports,所以在引用 这个模块的文件中 //只能看到module.exports的修改而看不到exports修改的
Node中的全局对象
Node中的 全局对象 为 global ====> 相当于浏览器中的 window
包 package
包就是将一组相关模块组合到一起,形成一个完整的工具
- 包的组成
- 包结构: 用于组织包中的各种文件,包含以下:
- (重要) package.json ===> 描述文件
- bin ===> 可执行的二进制文件
- lib ===> js代码
- doc ===> 文档
- test ===> 单元测试
- 包描述文件: 描述包的相关信息,以供使用者了解
- 包结构: 用于组织包中的各种文件,包含以下:
NPM包管理器 (Node Package Manager)
Npm参考 -阮一峰
常用命令
1. npm -v ===> 查询npm的版本
2. npm =====> 查看帮助说明
3. npm search 包名 =====> 搜素模块包
4. npm install 包名 ====> 安装包
5. npm install 包名 --save ====> 安装并将包添加到依赖(dependencies)中
6. npm install 包名 --save-dev ====> 安装并将包添加到开发依赖(devDependencies)中
7. npm install ===> 安装当前环境中依赖的所有包
8. (重要) npm install -g 包名 ===> 全局模式安装包
9. npm remove 包名 或者 npm r 包名 =====> 删除模块包
10. (重要) npm init ===> 初始化生成package.json文件
需要注意:
1. 通过npm或cnpm下载的包都放在node_modules文件夹中,使用时直接将包名引入即可
2. node在引入模块的时候,如果直接使用模块名字,会首先在当前目录中的node_modules中寻找是否有该模块,如果有则使用,没有则去上一级目录中的node_modules中寻找,循环直到当前包所在磁盘根目录,找到使用,没找到报错
package.json参数详解
{
"name": "当前项目的名称",
"version": "1.2.3 版本(遵守“大版本.次要版本.小版本”的格式)",
"author": "作者",
"description": "关于包的描述",
"keywords":["node.js","javascript"," ===>包的描述关键字"],
"repository": { 包所在的远程仓库
"type": "git",
"url": "https://path/to/url"
},
"license":"许可",
"engines": {"node": "指明了该项目所需要的node.js版本"},
"bugs":{"url":"http://path/to/bug",
"email":"bug@example.com",
"用途": "bug提交的地址或者邮箱"
},
"contributors":[{"name":"李四","email":"lisi@example.com"},
{"用途": "标明开放包的贡献人士"}],
"scripts": {
"start": "node ./index.js",
"用途": "使用node run [key]可以运行script中key对应的value中的代码"
"例如": "在终端运行node run start就等于运行node ./index.js"
},
"dependencies": {
"express": "latest",
"mongoose": "~3.8.3",
"handlebars-runtime": "~1.0.12",
"express3-handlebars": "~0.5.0",
"MD5": "~1.2.0",
"用途": "所依赖的环境(必须有这些包才能正常运行当前包)"
},
"devDependencies": {
"bower": "~1.2.8",
"grunt": "~0.4.1",
"用途": "开发这个包时用的环境,但是在生成环境中可以省略的包"
},
"main": {"用途": "指定整个包的入口文件 默认是: index.js"}
}
Buffer 缓冲区
- Buffer的结构、操作的方法与数组很像
- Buffer弥补了 数组 不能储存二进制数据 的缺点
- Buffer存储二进制数据,但是以16进制的方式显示
- 单个元素的范围是 00 - ff ==> 00 - 255 ==> 00000000 - 11111111
- Buffer中一个元素等于1 byte(说明Buffer对象的长度 = 占用内存的大小)
- 计算机知识:
- 最小单位是: bit,最小基本单位是: byte
- 一个0或1,称为1位或1 bit
- 8 bit = 1 byte
- 1024 byte = 1kb
- 1024kb = 1mb
- 1024mb = 1gb
- 1024gb = 1tb
- Buffer的大小一旦确定了就不能再修改
- Buffer相关方法
Buffer.from(str) //将一个字符串转换为buffer buffObj.toString() //将buffer实例对象转换为字符串 Buffer.alloc(size) //创建一个指定大小的Buffer Buffer.allocUnsafe(size)//创建一个指定大小的Buffer,但是其中是用过的内存(没有清空)
fs(file system) 文件系统
fs就是通过Node来操作系统中的文件
fs是核心模块,不需要下载便可直接引入
文件写入
-
同步写入文件
var fs = require('fs'); //引入fs核心模块 //找到并打开文件 var f = fs.openSync('test.txt','w'); //以同步方式写入文件 fs.writeSync(f,'write success'); //保存并关闭同步模式的文件 fs.closeSync(f);
-
异步写入文件
//异步操作文件 var fs = require('fs'); //引入fs核心模块 //找到并打开文件 //fs.open(path,flag,callback(e,f)) //e是错误信息,没错误返回null //f是文件的标识符 fs.open('test2.txt','w',function(error,file){ if(error){ console.log(error); } //以异步模式写入文件 fs.write(file,'异步写入成功',function(e){ if(e){ console.log(e); } console.log('写入方法的回调已被执行'); }); //保存并关闭异步模式的文件 fs.close(file,function(e){ if(e){ console.log(e); } console.log('文件关闭成功'); }); });
-
简单文件写入
-
同步的
//同步的 fs.writeFileSync('simpleWrite.txt','简单文件写入-同步 成功')
-
异步的
//异步的 fs.writeFile('simpleWrite2.txt','简单文件写入-异步 成功',function(e){ if(e) { console.log(e); } console.log('write success'); })
-
-
流式文件写入
解决同步、异步、简单文件写入三种模式性能较差,容易导致内存溢出的问题
var fs = require('fs'); //引入fs核心模块
//创建一个可写流
var ws = fs.createWriteStream('writeStream.txt');
//通过可写流向文件中写入内容
ws.write("通过可写流写入第1个内容\n");
ws.write("通过可写流写入第2个内容\n");
ws.write("通过可写流写入第3个内容\n");
//关闭可写流
ws.end()
文件读取
-
同步文件读取
-
简单文件同步读取
var fs = require("fs"); //找到并读取文件 var f = fs.readFileSync('test.txt'); console.log(f.toString());
-
异步文件读取
-
简单文件异步读取
var fs = require("fs"); //找到并读取文件 var f = fs.readFile('test2.txt',function(e,f){ if(e){ console.log('读取失败...'); console.log(e); } console.log(f.toString()); });
-
流式文件读取
可以多次将文件读取到内存中
//流式文件读取 var fs = require("fs"); //创建一个可读流 var rs = fs.createReadStream('writeStream.txt'); //创建一个可写流 var ws = fs.createWriteStream('writeStream2.txt'); /*//读取可读流中的数据,必须绑定一个data事件,绑定完毕后会自动开始读取数据 rs.on('data',function(data){ console.log(data.toString()); //将可读流中的数据复制写入到 writeStream2.txt 中 ws.write(data); }) rs.once('close',function(){ ws.close(); })*/ //简化读写过程 rs.pipe(ws); //自动读取 自动写入 自动关闭
其他方法
-
检查文件状态
var fs = require("fs"); fs.stat('test.txt',function(error,statusInfo){ console.log(statusInfo); //statusInfo中的各种检测 console.log(statusInfo.isFile()); console.log(statusInfo.isDirector()); })
-
删除文件
//删除一个文件 var fs = require("fs"); fs.unlinkSync('beenRemove.txt')
-
修改/限制文件的大小
var fs = require("fs"); fs.truncateSync('test.txt',3) //将test.txt文件修改为3 bytes大小
-
创建文件夹
var fs = require("fs"); fs.mkdirSync('newCollect');
-
列出文件夹中的所有文件
var fs = require("fs"); fs.readdir('./',function(error,files){ console.log(error); console.log(typeof files); //Object array console.log(files.length); console.log(files); })
-
删除文件夹
var fs = require("fs"); fs.rmdirSync('newCollect');
-
重命名文件夹
var fs = require("fs"); fs.rename('newCollect','newCollects',function(){ console.log('dd'); });
-
监听文件
var fs = require("fs"); fs.watchFile('test.txt',{interval:1000},function(curr,prev){ console.log('File has been modify'); console.log(curr); //修改前的stat(文件的status状态信息)对象 console.log(prev); //修改后的stat(文件的status状态信息)对象 })