官方文档
中文文档
Node.js是什么
Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。
Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。
Node.js 的包管理器 npm,是全球最大的开源库生态系统。
以上是中英文两种方式对Node.js的概括,需要我们明确的是,Node.js既不是一门编程语言,也不是一个某个领域的框架,而是一个javascript的运行环境
。
chrome V8引擎
Chrome V8, or simply V8, is an open-source JavaScript engine developed by The Chromium Project for Google Chrome and Chromium web browsers.[5] The project’s creator is Lars Bak.[6] The first version of the V8 engine was released at the same time as the first version of Chrome: September 2, 2008. It has also been used in Couchbase, MongoDB and Node.js that are used server-side.
摘自于wiki,简而言之,即v8是google开源的javascript引擎,被用来在chrome中解释javascript。
v8
下载Node.js
从官网可知,当前最新版本是9.4.0,长期服务版本是8.9.4,因为Node.js版本迭代比较快,在开发中,有时需要高版本,有时需要低版本,所以我们不推荐直接下载安装。我们可以使用Node.js版本管理工具nvm
。
NVM
nvm
按照文档进行下载,完成之后我们命令行输入以下命令验证:
nvm --version
有反馈说明安装成功。
我们通过nvm来查看有哪些node版本可供下载:
nvm ls-remote
v0.1.14
v0.1.15
v0.1.16
v0.1.17
v0.1.18
v0.1.19
v0.1.20
v0.1.21
v0.1.22
v0.1.23
v0.1.24
v0.1.25
v0.1.26
v0.1.27
v0.1.28
v0.1.29
v0.1.30
v0.1.31
v0.1.32
v0.1.33
v0.1.90
v0.1.91
v0.1.92
v0.1.93
v0.1.94
v0.1.95
v0.1.96
v0.1.97
v0.1.98
v0.1.99
v0.1.100
v0.1.101
v0.1.102
v0.1.103
v0.1.104
v0.2.0
v0.2.1
v0.2.2
v0.2.3
v0.2.4
v0.2.5
v0.2.6
v0.3.0
v0.3.1
v0.3.2
v0.3.3
v0.3.4
v0.3.5
v0.3.6
v0.3.7
v0.3.8
v0.4.0
v0.4.1
v0.4.2
v0.4.3
v0.4.4
v0.4.5
v0.4.6
v0.4.7
v0.4.8
v0.4.9
v0.4.10
v0.4.11
v0.4.12
v0.5.0
v0.5.1
v0.5.2
v0.5.3
v0.5.4
v0.5.5
v0.5.6
v0.5.7
v0.5.8
v0.5.9
v0.5.10
v0.6.0
v0.6.1
v0.6.2
v0.6.3
v0.6.4
v0.6.5
v0.6.6
v0.6.7
v0.6.8
v0.6.9
v0.6.10
v0.6.11
v0.6.12
v0.6.13
v0.6.14
v0.6.15
v0.6.16
v0.6.17
v0.6.18
v0.6.19
v0.6.20
v0.6.21
v0.7.0
v0.7.1
v0.7.2
v0.7.3
v0.7.4
v0.7.5
v0.7.6
v0.7.7
v0.7.8
v0.7.9
v0.7.10
v0.7.11
v0.7.12
v0.8.0
v0.8.1
v0.8.2
v0.8.3
v0.8.4
v0.8.5
v0.8.6
v0.8.7
v0.8.8
v0.8.9
v0.8.10
v0.8.11
v0.8.12
v0.8.13
v0.8.14
v0.8.15
v0.8.16
v0.8.17
v0.8.18
v0.8.19
v0.8.20
v0.8.21
v0.8.22
v0.8.23
v0.8.24
v0.8.25
v0.8.26
v0.8.27
v0.8.28
v0.9.0
v0.9.1
v0.9.2
v0.9.3
v0.9.4
v0.9.5
v0.9.6
v0.9.7
v0.9.8
v0.9.9
v0.9.10
v0.9.11
v0.9.12
v0.10.0
v0.10.1
v0.10.2
v0.10.3
v0.10.4
v0.10.5
v0.10.6
v0.10.7
v0.10.8
v0.10.9
v0.10.10
v0.10.11
v0.10.12
v0.10.13
v0.10.14
v0.10.15
v0.10.16
v0.10.17
v0.10.18
v0.10.19
v0.10.20
v0.10.21
v0.10.22
v0.10.23
v0.10.24
v0.10.25
v0.10.26
v0.10.27
v0.10.28
v0.10.29
v0.10.30
v0.10.31
v0.10.32
v0.10.33
v0.10.34
v0.10.35
v0.10.36
v0.10.37
v0.10.38
v0.10.39
v0.10.40
v0.10.41
v0.10.42
v0.10.43
v0.10.44
v0.10.45
v0.10.46
v0.10.47
v0.10.48
v0.11.0
v0.11.1
v0.11.2
v0.11.3
v0.11.4
v0.11.5
v0.11.6
v0.11.7
v0.11.8
v0.11.9
v0.11.10
v0.11.11
v0.11.12
v0.11.13
v0.11.14
v0.11.15
v0.11.16
v0.12.0
v0.12.1
v0.12.2
v0.12.3
v0.12.4
v0.12.5
v0.12.6
v0.12.7
v0.12.8
v0.12.9
v0.12.10
v0.12.11
v0.12.12
v0.12.13
v0.12.14
v0.12.15
v0.12.16
v0.12.17
v0.12.18
iojs-v1.0.0
iojs-v1.0.1
iojs-v1.0.2
iojs-v1.0.3
iojs-v1.0.4
iojs-v1.1.0
iojs-v1.2.0
iojs-v1.3.0
iojs-v1.4.1
iojs-v1.4.2
iojs-v1.4.3
iojs-v1.5.0
iojs-v1.5.1
iojs-v1.6.0
iojs-v1.6.1
iojs-v1.6.2
iojs-v1.6.3
iojs-v1.6.4
iojs-v1.7.1
iojs-v1.8.1
iojs-v1.8.2
iojs-v1.8.3
iojs-v1.8.4
iojs-v2.0.0
iojs-v2.0.1
iojs-v2.0.2
iojs-v2.1.0
iojs-v2.2.0
iojs-v2.2.1
iojs-v2.3.0
iojs-v2.3.1
iojs-v2.3.2
iojs-v2.3.3
iojs-v2.3.4
iojs-v2.4.0
iojs-v2.5.0
iojs-v3.0.0
iojs-v3.1.0
iojs-v3.2.0
iojs-v3.3.0
iojs-v3.3.1
v4.0.0
v4.1.0
v4.1.1
v4.1.2
v4.2.0 (LTS: Argon)
v4.2.1 (LTS: Argon)
v4.2.2 (LTS: Argon)
v4.2.3 (LTS: Argon)
v4.2.4 (LTS: Argon)
v4.2.5 (LTS: Argon)
v4.2.6 (LTS: Argon)
v4.3.0 (LTS: Argon)
v4.3.1 (LTS: Argon)
v4.3.2 (LTS: Argon)
v4.4.0 (LTS: Argon)
v4.4.1 (LTS: Argon)
v4.4.2 (LTS: Argon)
v4.4.3 (LTS: Argon)
v4.4.4 (LTS: Argon)
v4.4.5 (LTS: Argon)
v4.4.6 (LTS: Argon)
v4.4.7 (LTS: Argon)
v4.5.0 (LTS: Argon)
v4.6.0 (LTS: Argon)
v4.6.1 (LTS: Argon)
v4.6.2 (LTS: Argon)
v4.7.0 (LTS: Argon)
v4.7.1 (LTS: Argon)
v4.7.2 (LTS: Argon)
v4.7.3 (LTS: Argon)
v4.8.0 (LTS: Argon)
v4.8.1 (LTS: Argon)
v4.8.2 (LTS: Argon)
v4.8.3 (LTS: Argon)
v4.8.4 (LTS: Argon)
v4.8.5 (LTS: Argon)
v4.8.6 (LTS: Argon)
v4.8.7 (Latest LTS: Argon)
v5.0.0
v5.1.0
v5.1.1
v5.2.0
v5.3.0
v5.4.0
v5.4.1
v5.5.0
v5.6.0
v5.7.0
v5.7.1
v5.8.0
v5.9.0
v5.9.1
v5.10.0
v5.10.1
v5.11.0
v5.11.1
v5.12.0
v6.0.0
v6.1.0
v6.2.0
v6.2.1
v6.2.2
v6.3.0
v6.3.1
v6.4.0
v6.5.0
v6.6.0
v6.7.0
v6.8.0
v6.8.1
v6.9.0 (LTS: Boron)
v6.9.1 (LTS: Boron)
v6.9.2 (LTS: Boron)
v6.9.3 (LTS: Boron)
v6.9.4 (LTS: Boron)
v6.9.5 (LTS: Boron)
v6.10.0 (LTS: Boron)
v6.10.1 (LTS: Boron)
v6.10.2 (LTS: Boron)
v6.10.3 (LTS: Boron)
v6.11.0 (LTS: Boron)
v6.11.1 (LTS: Boron)
v6.11.2 (LTS: Boron)
v6.11.3 (LTS: Boron)
v6.11.4 (LTS: Boron)
v6.11.5 (LTS: Boron)
v6.12.0 (LTS: Boron)
v6.12.1 (LTS: Boron)
v6.12.2 (LTS: Boron)
v6.12.3 (Latest LTS: Boron)
v7.0.0
v7.1.0
v7.2.0
v7.2.1
v7.3.0
v7.4.0
v7.5.0
v7.6.0
v7.7.0
v7.7.1
v7.7.2
v7.7.3
v7.7.4
v7.8.0
v7.9.0
v7.10.0
v7.10.1
v8.0.0
v8.1.0
v8.1.1
v8.1.2
v8.1.3
v8.1.4
v8.2.0
v8.2.1
v8.3.0
v8.4.0
v8.5.0
v8.6.0
v8.7.0
v8.8.0
v8.8.1
v8.9.0 (LTS: Carbon)
v8.9.1 (LTS: Carbon)
v8.9.2 (LTS: Carbon)
v8.9.3 (LTS: Carbon)
v8.9.4 (Latest LTS: Carbon)
v9.0.0
v9.1.0
v9.2.0
v9.2.1
v9.3.0
-> v9.4.0
通过这条命令,验证我们之前的想法,node的版本非常零碎。我们观察可以看到,有一些版本的名称叫iojs
。这是因为node团队曾经有一段时间分成了两个团队。
我们下载v8.9.4并使用
nvm install 8.9.4
nvm use 8.9.4
node --version
v8.9.4
通过以上命令,我们成功下载并安装了8.9.4版本。
入门
交互式环境
我们进入命令行,输入以下命令:
node
// 此时进入了交互式环境
1+1
2
var s = 'hello world'
console.log(s)
hello world
可以看到,我们输入node命令之后,就好像进入了浏览器的console控制台一样。
node运行js文件
创建js文件并编写代码:
mkdir node-demo
cd node-demo
touch index.js
vi index.js //写入console.log('hello world')
node index.js
hello world
我们在index.js中编写了一条最简单的语句。然后使用node命令来运行这个文件,命令行正常进行了打印。
网络应用程序
As an asynchronous event driven JavaScript runtime, Node is designed to build scalable network applications. In the following "hello world" example, many connections can be handled concurrently. Upon each connection the callback is fired, but if there is no work to be done, Node will sleep.
const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
在官网的About Node.js
部分中,有以上一段文字和程序。它告诉我们,Node.js是一个基于事件驱动的异步javascript运行环境,它被设计用来构建可伸缩的网络应用程序。
我们访问localhost:3000
,可以正常显示hello world
。
Node.js重要概念
通过上面的学习,我们已经积累了两个概念:
- 异步
- 事件驱动
事实上,如果我们队Node.js还有了解的话,我们之后Node.js还有一个特性:
- 单线程
以上三个概念或者说特性,是我们了解Node.js的基本路线,也是我们在生产环境中使用Node.js的理论来源。
异步
异步的另一个表达方式叫非阻塞
。最直观的理解就是,我们在读取一个超大文件时,cpu不会死等硬盘去读取数据,而是继续执行后面的代码,等文件读取结束之后,以回调的形式告知程序。
我们以fs为例,fs是Node.js操作文件的函数库:
fs.readFile('/hello.txt', (err, data) => {
if (err) throw err;
console.log(data);
});
我们可以看到,读取文件是一个异步的操作,文件的内容由回调返回。这样的特性,在许多编程语言中是没有的。
我们通过实际代码来测试:
async.js
var fs = require('fs');
fs.readFile('./1.txt',function(err,data){
console.log(data.toString());
});
console.log('hello async.js');
1.txt
hello 1.txt
我们输入命令:
node async.js
hello async.js
hello 1.txt
我们可以看到,结果不言而喻。
单线程
我们知道,java语言开发web应用时,就是采用的多线程的模型,每当一个用户访问进来时,都会创建一个线程来处理。这样的一大弊端就是,频繁的创建和销毁线程,对cpu带来和很大的负担,造成了cpu资源的浪费。然而,Node.js就走了一条与java完全不同的策略,在Node.js中使用的是单线程的模型
。
我们来验证Node.js是否真的是单线程:
修改之前的app.js
const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
console.log('=====================');
//s没有定义
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
console.log(s);
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
通过以上代码实验,我们可以这样认识,第一个用户成功访问后,服务器出现了异常,第二个用户再访问时,服务已经断开,无法应答。所以说,用Node写后端对我们的代码质量要求非常高,一个错误就能搞垮程序,其它人就无法访问了。单线程的好处就是,减小了创建和销毁线程的开销,在低端机器上也能发挥最大的性能
。
事件驱动
可以说,Node之所以能在单线程环境中,实现异步IO,根本原来就是,Node实现的事件驱动算法机制
。
我们知道,java能实现异步编程,是因为有多线程的存在,那么Node靠单线程是怎么实现异步IO的,是一个值得探讨的问题
。
我们思考一个场景,比如说,现在有一家黄焖鸡米饭小店,服务员只有一个人
,她需要兼顾迎接客人,询问客人吃什么,从后厨上菜品,擦桌子
一系列事情。这样就导致,她要把所有的事情都做好,就不能在一位客人那里等着客人照着菜单选。她会告诉客人,选好菜直接叫她,她会利用客人选菜的时间,去把刚才另外的客人吃完的桌子擦干净。这就是事件驱动
。什么时间点应该去做哪件事情就是异步事件算法应该实现的策略
。
所以,Node就跟这位服务员一样,累死累活的干活,效率还是非常高的。
npm (Node Package Manager)
npm是node包管理器,类似于java中maven,gradle。
npm
npm之上有非常丰富的第三方javascript函数库,减少了我们重复找轮子的过程。比如:
lodash
axios
npm的使用
在node安装成功之后,npm即会随之安装,我们验证npm
是否安装成功:
npm --vserion
5.6.0
出现数字,说明本地已经有了npm工具。
我们用npm创建项目:
rm -rf node-demo
mkdir node-demo
npm init
一路回车,npm会在根目录下生成一个名为package.json
的文件,它记录这个项目的相关信息。
在讲解命令用法之前,先梳理一下npm相关命令:
- npm init 根据选择项,为项目创建package.json文件
- npm install 根据package.json中的dependencies和devdependencies下载依赖包
- npm install package-name 下载指定的包,并添加到dependencies中
- npm install package-name --save 下载指定的包,并添加到dependencies中
- npm install package-name --save-dev 下载指定的包,并添加到devdependencies中
- npm install package-name -g 安装到全局 一般在安装cli工具时使用 -g
cat package.json
{
"name": "demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
有版本,描述,协议等内容。
我们安装lodash
npm install lodash --save
成功之后,我们观察到文件中有了一些变化,package.json中。多了一行内容:
"dependencies": {
"lodash": "^4.17.4"
}
--save
命令不仅将包安装,并将包的名称加入到dependencies
中。
根目录中多了一个node_modules
文件夹,里面存放着我们下载的lodash。
我们所有通过npm install
安装的包都会放置在node_modules文件夹中。
此时,我们就可以使用lodash:
var _ = require('lodash')
_.forEach([1, 2], function(value) {
console.log(value);
});
1
2
node中,使用require
引入模块。
cnpm
cnpm是淘宝开源的一个代替npm工具,使用的淘宝镜像,速度非常快。
cnpm
安装:
npm install -g cnpm --registry=https://registry.npm.taobao.org
之后,任何使用npm的地方我们都可以使用cnpm
。
yarn
yarn也是一个npm客户端,与npm相比,速度更快更安全,推荐用yarn来代替npm。
yarn
Node.js模块化
我们之前用到require函数
,知道了可以引入模块,与之对应的还有向外暴露模块,向外暴露有两种方式:
- exports
- module.exports
创建util.js
function pingfang(x) {
return x * x ;
}
exports.pingfang = pingfang
修改index.js
var util = require('./util.js')
console.log(util.pingfang(3))
可以正常得出结果为9.
创建user.js
function User(name,age) {
this.name = age;
this.age = age;
}
User.prototype.say = function() {
console.log('my name is '+ this.name);
}
module.exports = User
修改index.js
var User = require('./user.js')
var user = new User('xiaoming',12);
user.say();
可以正常输出。
至此,我们就介绍完了Node.js中最重要的内容。