Node.js
Node.js是一个开源和跨平台的JavaScript运行时环境
Node.js基于Chromes的V8JavaScript解析引擎,使JavaScript代码可以在浏览器之外运行
安装Node.js
所有主流平台的官方软件包都可以在 http://nodejs.cn/download/ 获得
使用Node.js
基本使用方法
在命令行中使用node
命令来运行Node.js脚本的命令,node命令后跟要执行的JavaScript代码文件
node script.js
如果省略文件名,则会开启REPL模式
REPL:运行评估打印循环,是一种编程语言环境,它使用单个表达式作为用户输入,并在执行后将结果返回到控制台
>node
>console.log("hello world");
hello world
undefined
上述代码的执行结果,其中hello world是console.log()的执行结果,而undefined是console.log()方法的返回值
tab键的妙用:
- tab键会尝试自动补全所写的内容
- 包括REPL模式下已定义或预定义的变量
- 和使用node命令执行文件时的文件名
从命令行传入参数
node script.js Kiana
获取命令行传入的参数
使用Node.js中的内置对象process的argv属性,该属性是一个包含所有命令行参数的数组
js文件
process.argv.forEach((element,index) => {
console.log(`${index}:${element}`);
});
命令行代码
>node script.js kiana
返回的结果中当element的值为kiana时 index的值为2
index的值为2是因为在命令行中第一个参数是node命令的完整路径,第二个参数是正在被执行文件的完整路径,所有实际需要的参数从第三个位置开始
可以通过切割数组,排除前两个参数
const args = porcess.argv.slice(2);
console.log(args[0]);
输出到命令行
Node.js提供了console模块,用来实现与命令行的交互,使用方法基本和浏览器中console的使用方法相同
-
console.log()
-
console.clear() 清空命令行
-
console.count() 当打印时会统计相同字符串的次数
-
const arr = "hello world".split(""); arr.forEach(ele=>{ console.count(ele); }) //它在打印信息时不会去重,只是添加了计数
-
-
console.time() 与timeEnd一同测量,函数运行所需要的时间
-
console.timeEnd()
-
function fun (){ const arr = "hello world".split(""); arr.forEach(ele => { console.count(ele); }) } //time()和timeEnd()中的参数,是一个标签信息,用来标识计算的是相同标签名之间的执行时间 console.time("fun()") fun(); console.timeEnd("fun()")
-
从命令行接收输入
Node.js提供了readline模块,可以通过输入流来读取数据
const readline = require("readline").createInterface({
//设置输入流和输出流
input:process.stdin,
output:process.stdout
})
//使用question方法
//第一个参数会显示在命令行中
//第二个参数使用用户输入数据的回调
readline.question("what is your name?",name=>{
console.log("hello " +name);
//使用完后要关闭流
readline.close()
})
Node.js的模块化
模块的分类
- 内置模块:由Node.js官方提供的模块 如:readline、fs、path等
- 自定义模块:自己创建的模块
- 第三方的模块:第三方提供的,非官方的模块,需要下载使用
加载模块
通过require()方法加载模块
require('fs') // 内置模块加载
require('./cust.js') //用户自定义模块加载 加载自定义模块时,要加路径
require('moment') //第三方模块加载
//在使用require导入模块时,模块内的所有代码都会执行
自定义模块
模块作用域:在模块中定义的变量、方法等,只能在当前模块内被访问
script标签引入的不同js文件最终会合并的同一作用域中
module对象
每个js模块中都含有module对象,保存了一个模块内的基本信息
module.exports对象可以经模块内的成员共享出去,供外界使用
require()方法导入的就是module.exprots对象导出的内容
注意:在导入时永远以module.exprots指向的对象为准
module.exports.username = 'kiyana';
//为简化书写,node提供了另一个对象exports,exports对象默认和module.exports指向同一内存空间,
exports.sayHello = function(){
console.log("hello!")
}
//require方法导入时,结果为{username:'kiyana,sayHello:[function:sayHello]'}
//注意exports和module.exports不是同一个对象,在使用exports时不能给它重新赋一个对象
module.exports = {
name:'符华'
}
exports = {
name:"爱莉希雅"
}
//require方法导入时,结果为{name:'符华'} 在导入时永远以module.exprots指向的对象为准
模块的加载机制
优先从缓存中加载
模块在第一次加载后就会被缓存,所有多次调用require方法不会导致模块的代码被执行多次
内置模块的加载机制
内置模块的加载优先级更高
自定义模块的加载机制
使用require加载自定义模块时,必须以./或…/开头的路径标识符,否则node会把它当做内置模块或第三方模块进行加载
如果在加载自定义模块时省略文件拓展名,node.js会按顺序尝试加载以下文件
- 确切的文件名
- 补齐.js进行加载
- 补齐.json进行加载
- 补齐.node进行加载
- 加载失败
第三方模块的加载机制
如果传递给require的模块标识符不是一个内置模块,也没有以./或…/开头,则node.js会从当前模块的父目录开始尝试从/node_modules文件夹中加载第三方模块,如果当前模块的父目录没有的移动到上一层目录中继续寻找,直到文件系统的根目录
目录作为模块加载(包的加载机制)
当把目录作为模块标识符,传递给require进行加载时
- 在被加载的目录下查找一个叫做package.json的文件,并寻找main属性作为require加载的入口
- 如果目录中没有package.json或main入口不存在或无法解析,则Node.js会试图加载目录下的index.js文件
- 如果以上都失败的Node.js会在终端报
npm
Node Package Manager(简称 npm包管理工具)
在项目中安装包
npm install 包名
简写方式:
npm i 包名
只写包名默认使用最新的包,可以在包名后加@版本号,来下载使用指定版本的包
npm i 包名@版本号
npm命令下载的包会存放在执行命令目录下的node_modules目录下,同时还有一个package-lock.json的配置文件用来记录包的信息
包管理配置文件
package.js配置文件是项目的清单,它可以通过配置不同的属性,做很多互不相干的事
{
"name": "test-project",
"version": "1.0.0",
"description": "A Vue.js project",
"main": "src/main.js",
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
},
"dependencies": {
"vue": "^2.5.2"
},
"devDependencies": {
"webpack-merge": "^4.1.0"
},
"engines": {
"node": ">= 6.0.0",
},
"browserslist": ["> 1%", "last 2 versions", "not ie <= 8"]
}
version
表明了当前的版本。name
设置了应用程序/软件包的名称。description
应用程序/软件包的简短描述。main
设置了应用程序的入口点。private
如果设置为true
,则可以防止应用程序/软件包被意外地发布到npm
。scripts
定义了一组可以运行的 node 脚本。dependencies
设置了作为依赖安装的npm
软件包的列表。devDependencies
设置了作为开发依赖安装的npm
软件包的列表,只在开发阶段使用的依赖包engines
设置了此软件包/应用程序在哪个版本的 Node.js 上运行。browserslist
用于告知要支持哪些浏览器(及其版本)。
当存在package.json配置文件时,通过nop install 命令会自动读取该文件并安装其中配置的所有包
npm的其他用法
卸载包
npm uninstall 包名
安装包到devDependencies节点
如果有些包只在项目开发时使用,在项目上线后不会用到,可以将这些包记录到devDependencies节点中
npm i 包名 -D
切换npm下载包的镜像源
查看当前使用的镜像源
npm confing get registry
设置镜像源
npm config set registry=https://registry.npm.taobao.org/
下载nrm工具切换镜像源
npm i nrm -g // -g表示将该包设置到全局
查看服务器列表
nrm ls
切换服务器
nrm use 服务器名
全局包
在执行npm install 时加参数 -g 表示将包安装到全局
全局包默认安装在 C:\Users\username\AppData\Roaming\npm\node_modules
安装和卸载全局包
npm i 包名 -g
npm uninstall 包名 -g
事件循环
javaScript的代码运行在单个线程上,单线程的弊端就是就是可能遇到阻塞情况(如定时器、异步操作等)而事件循环解决了这一问题
事件循环会将产生阻塞状态的操作,放入一个消息队列中,优先执行不会产生阻塞的操作,当主程序全部执行完毕后,才会处理消息队列中的东西
消息队列:用户触发的事件(如单击或键盘事件、或获取响应)也会在此排队
function first(){
console.log("first");
}
function second(){
console.log("second");
}
function thrid(){
first();
//这是一个定时器会产生阻塞状态,即使它很快就会执行
setTimeout(second,0);
console.log("thrid");
}
thrid(); //=>first thrid second
作业队列
ES6中引入了作业队列的概念,当使用Promise时需要异步操作的内容会被放到作业队列中,这种方式会尽快执行异步函数的结果,而不是最后执行
function first() {
console.log("first");
}
function second() {
console.log("second");
}
function third() {
//first
setTimeout(first, 0);
//second
new Promise((resolve, reject) => {
resolve(second());
});
//third
console.log("third");
}
third(); //=>second third first
定时器
-
setTimeout(回调函数,时间)
-
指定一个函数,稍后执行
-
时间为毫秒值,1000毫秒=1秒
-
const fun = function (firstParam, secondParam) { console.log(firstParam, secondParam); } //可以给设置的回调函数传达参数 setTimeout(fun,2000,"kiana","bronya");
-
-
setInterval(回调函数,时间)
-
指定一个回调函数,根据指定的时间,循环调用
-
setInterval方法会返回一个定时器id,可以通过clearInterval(id)清除定时器,终止函数的循环调用
-
let flag = true; let num = 0; const id = setInterval(() => { if (flag === false) { //当某些条件是flag为false时,清除定时器 clearInterval(id); } num = parseInt(Math.random() * 10) if(num>=9){ flag = false; } console.log("定时器启动了") }, 1000)
-
fs文件模块
fs模块时Node.js官方提供的、用来操作文件的模块
fs文件读写操作
使用步骤:
const fs = require('fs'); //导入模块
//fs.wirteFile(path,data[,options],callback)
//path:写入的文件路径,会自动创建文件,但不会创建文件夹
//data:要写入的内容
//options:写入时的文件编码
//callback:错误信息的回调函数
fs.writeFile("./1.txt", "hello world", 'utf8', function (err) {
console.log(err);
})
//fs.readFile(path,[,options],callback)
fs.readFile("./1.txt", 'utf8', function (err, dataStr) {
//dataStr:读取的内容
if (err) {
console.log(err);
} else {
console.log(dataStr);
}
})
fs文件夹操作
-
fs.mkdir()和fs.mkdirSync() 创建文件夹 带Sync的是同步版本
-
fs.mkdirSync("./files");
-
-
fs.readdir()和fs.readdirSync() 读取文件夹信息
-
fs.readdirSync("./files");
-
-
fs.rename()和fs.renameSync() 重命名文件夹
-
fs.renameSync("./files","./newFiles",err=>{console.log(`${err?err:""}`)})
-
-
fs.rmdir()和fs.rmdirSync() 删除空文件夹
-
fs.rmdirSync("./files")
-
path路径模块
node.js内置的操作路径信息的模块
- path.join() 拼接字符串
- path.basename(path[,ext]) 返回路径中的最后一部分,第二个参数是拓展名,设置拓展名后会删除返回结果中的拓展名部分
- path.extname(path) 返回文件的拓展名
const path = require("path");
//__dirname表示当前文件父目录的绝对路径
let pt = path.join(__dirname,"1.txt");
console.log(pt)//=>C:\Users\username\Desktop\NodePractice\1.txt
console.log(path.basename(pt)); //=>1.txt
console.log(path.basename(pt,path.extname(pt))); //=>1
http模块
创建HTTP服务器
const http = require('http')
const port = 80;
const server = http.createServer((request,response) => {
//request 是请求对象,包含了与客户端相关的数据和属性
//response 是响应对象,包含了服务端相关的数据和属性,使用response.end(data)方法给客户端发送信息
//设置状态码
response.statusCode = 200
//设置响应头,否则中文会乱码
response.setHeader('Content-Type', 'text/html;charset=utf-8');
response.end('你好世界!!!')
})
server.listen(port, () => {
console.log(`http server is running http://127.0.0.1:${port}/`)
})