├── .gitignore
├── 404.html
├── LICENSE
├── README.md
├── _config.yml
├── app.js
├── count.js
├── handler.js
├── hello-world-web.js
├── index.html
├── p11.js
├── p2.js
├── p3.js
├── p4.js
├── p5.js
├── p6.js
├── p7.js
├── p8.js
├── p9.js
├── package.json
├── readMe.txt
├── review.html
├── router.js
├── server.js
├── stuff
└── writeMe.txt
└── writeMe.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # next.js build output
61 | .next
62 |
--------------------------------------------------------------------------------
/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 | 404
11 |
12 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 able8
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # hello-nodejs
2 |
3 | 轻松学 Node.js 基础篇 入门
4 |
5 | 视频地址
6 |
7 | - [https://www.rails365.net](https://www.rails365.net/movies/qing-song-xue-nodejs-ji-chu-pian-1-ke-cheng-jie-shao-yu-kai-fa-huan-jing-da-jian)
8 | - [b站](https://www.bilibili.com/video/av21010015)
9 |
10 | 常用链接
11 |
12 | - [Node.js 官网](https://nodejs.org/zh-cn/)
13 | - [Node.js 中文网](http://nodejs.cn)
14 | - [CNode:Node.js专业中文社区](https://cnodejs.org)
15 |
16 | 看视频整理要点笔记:
17 |
18 | ---
19 |
20 | - [目录](#hello-nodejs)
21 | - [1.介绍与开发环境搭建](#1%E8%AF%BE%E7%A8%8B%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA)
22 | - [2.全局对象](#2%E5%85%A8%E5%B1%80%E5%AF%B9%E8%B1%A1)
23 | - [3.回调函数](#3%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0)
24 | - [4.模块](#4%E6%A8%A1%E5%9D%97)
25 | - [5.事件 events](#5%E4%BA%8B%E4%BB%B6-events)
26 | - [6.读写文件(同步和异步)](#6%E8%AF%BB%E5%86%99%E6%96%87%E4%BB%B6%E5%90%8C%E6%AD%A5%E5%92%8C%E5%BC%82%E6%AD%A5)
27 | - [7.创建和删除目录](#7%E5%88%9B%E5%BB%BA%E5%92%8C%E5%88%A0%E9%99%A4%E7%9B%AE%E5%BD%95)
28 | - [8.流和管道](#8%E6%B5%81%E5%92%8C%E7%AE%A1%E9%81%93)
29 | - [9.web 服务器 part1 介绍](#9web-%E6%9C%8D%E5%8A%A1%E5%99%A8-part1-%E4%BB%8B%E7%BB%8D)
30 | - [10.web 服务器 part2 响应JSON](#10web-%E6%9C%8D%E5%8A%A1%E5%99%A8-part2-%E5%93%8D%E5%BA%94json)
31 | - [11.web 服务器 part3 响应HTML页面](#11web-%E6%9C%8D%E5%8A%A1%E5%99%A8-part3-%E5%93%8D%E5%BA%94html%E9%A1%B5%E9%9D%A2)
32 | - [12.web 服务器 part4 用模块化思想组织代码](#12web-%E6%9C%8D%E5%8A%A1%E5%99%A8-part4-%E7%94%A8%E6%A8%A1%E5%9D%97%E5%8C%96%E6%80%9D%E6%83%B3%E7%BB%84%E7%BB%87%E4%BB%A3%E7%A0%81)
33 | - [13.web 服务器 part5 路由](#13web-%E6%9C%8D%E5%8A%A1%E5%99%A8-part5-%E8%B7%AF%E7%94%B1)
34 | - [14.web 服务器 part6 重构路由代码](#14web-%E6%9C%8D%E5%8A%A1%E5%99%A8-part6-%E9%87%8D%E6%9E%84%E8%B7%AF%E7%94%B1%E4%BB%A3%E7%A0%81)
35 | - [15.web 服务器 part7 使用 GET或 POST 请求 发送数据](#15web-%E6%9C%8D%E5%8A%A1%E5%99%A8-part7-%E4%BD%BF%E7%94%A8-get%E6%88%96-post-%E8%AF%B7%E6%B1%82-%E5%8F%91%E9%80%81%E6%95%B0%E6%8D%AE)
36 | - [16.包管理器 npm](#16%E5%8C%85%E7%AE%A1%E7%90%86%E5%99%A8-npm)
37 | - [17.package.json 文件](#17packagejson-%E6%96%87%E4%BB%B6)
38 | - [18.nodemon监控文件并重启服务](#18nodemon%E7%9B%91%E6%8E%A7%E6%96%87%E4%BB%B6%E5%B9%B6%E9%87%8D%E5%90%AF%E6%9C%8D%E5%8A%A1)
39 |
40 | ---
41 |
42 | ## 1.课程介绍与开发环境搭建
43 |
44 | - 主要包括
45 | - nodejs 基础知识
46 | - web 服务器
47 | - 异步 同步 阻塞 非阻塞
48 |
49 | - 课程基础
50 | - javascript 基础
51 | - html 基础
52 | - 命令行基础
53 |
54 | - Node.js 介绍
55 | - Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境
56 | - Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效
57 | - Node.js 的包管理器 npm,是全球最大的开源库生态系统
58 | - javascript 是脚本语言,需要解析器才能执行,浏览器就充当了解析器
59 | - 在Chrome中,解析器就是 V8 引擎,将 javascript 转换成 机器码
60 | - V8 引擎是开源的,由 C++ 语言编写,性能高
61 | - Node.js 高性能,事件驱动,非阻塞,生态圈很好
62 |
63 | - Node.js 安装
64 | - [官网](https://nodejs.org/zh-cn/) 下载安装即可,很小不到20M!
65 | - 验证是否成功,命令行输入 `node -v` 显示版本号如 `v8.11.4`
66 | - 按提示升级 npm,Update available 5.6.0 → 6.4.1, `npm i -g npm`
67 | - macOS 安装完提示如下
68 |
69 | ```sh
70 | This package has installed:
71 | • Node.js v8.11.4 to /usr/local/bin/node
72 | • npm v5.6.0 to /usr/local/bin/npm
73 | Make sure that /usr/local/bin is in your $PATH.
74 | ```
75 |
76 | - Node.js 用途
77 | - javascript 运行环境
78 | - 操作文件(grunt gulp webpack)
79 | - 操作数据库
80 | - 写后端 api
81 | - 命令行工具
82 | - web 开发
83 | - 聊天室
84 |
85 | - JavaScript 语句后应该加分号么?
86 | - [知乎讨论](https://www.zhihu.com/question/20298345)
87 | - 代码风格而已,没有定论
88 | - 少分号更易读,不累
89 | - 必须加分号情况很少见:一行开头是括号`(`或者方括号`[`的时候加上分号就可以了,其他时候都不要
90 | - 如果下一行的行首是`( [ / + -`之一的话,js不会自动在上一行句尾加上分号
91 |
92 | ## 2.全局对象
93 |
94 | - 全局对象
95 | - 不用导入,直接使用的对象
96 | - [官方文档](http://nodejs.cn/api/globals.html#globals_global_objects)
97 | - Buffer 类,用于处理二进制数据
98 | - console,用于打印 stdout 和 stderr
99 | - global, 全局的命名空间对象
100 | - process,进程对象
101 | - setTimeout(callback, delay[, ...args])
102 | - setInterval(callback, delay[, ...args])
103 | - setImmediate(callback[, ...args])
104 | - clearTimeout(timeoutObject)
105 | - clearInterval(intervalObject)
106 | - clearImmediate(immediateObject)
107 |
108 | - 以下变量虽然看起来像全局变量,但实际上不是
109 | - 全局变量在所有模块中均可使用
110 | - 以下对象作用域只在模块内,详见 [module文档](http://nodejs.cn/api/modules.html):
111 | - __dirname
112 | - __filename
113 | - exports
114 | - module
115 | - require()
116 |
117 | - 运行 `.js` 脚本文件
118 | - `node app` 或者 `node app.js`
119 |
120 | - 实践代码
121 |
122 | ```js
123 | console.log('hello world');
124 |
125 | setTimeout(function () {
126 | console.log("3 seconds have passed 2");
127 | }, 3000);
128 |
129 | // 箭头函数,es6的写法
130 | setTimeout(() => {
131 | console.log("3 seconds have passed 1");
132 | }, 3000);
133 |
134 | // 每间隔2秒不断执行
135 | setInterval(function () {
136 | console.log("2 seconds have passed");
137 | }, 2000);
138 |
139 |
140 | var time = 0
141 | var timer = setInterval(function () {
142 | time += 2;
143 | console.log(time + " seconds have passed");
144 | if (time > 6) {
145 | clearInterval(timer);
146 | console.log("clearInterval")
147 | }
148 | }, 2000)
149 |
150 | // 输出当前目录 和 带绝对路径的文件名
151 | console.log(__dirname)
152 | console.log(__filename)
153 |
154 | console.log('end')
155 | console.dir(global)
156 | ```
157 |
158 | ## 3.回调函数
159 |
160 | ```js
161 | function sayHi() {
162 | console.log('Hi')
163 | }
164 |
165 | sayHi() // 调用函数
166 |
167 | // 将匿名函数赋给变量
168 | var sayBye = function (name) {
169 | console.log(name + ' Bye')
170 | }
171 |
172 | sayBye()
173 |
174 | // 第一个参数是函数
175 | function callFunction(fun, name) {
176 | fun(name)
177 | }
178 |
179 | callFunction(sayBye, 'able')
180 | // 或者
181 | callFunction(function (name) {
182 | console.log(name + ' Bye')
183 | }, 'able')
184 | ```
185 |
186 | ## 4.模块
187 |
188 | - module 对象
189 | - 每个文件都被视为独立的模块
190 | - 每个模块中,module 指向表示当前模块的对象的引用
191 | - module 实际上不是全局的,而是每个模块本地的
192 | - module.exports 导出模块内的对象,方便其他对象引用
193 | - require() 引入模块
194 | - 当 Node.js 直接运行一个文件时,require.main 会被设为它的 module
195 | - 可以通过 require.main === module 来判断一个文件是否被直接运行
196 | - module 提供了一个 filename 属性(通常等同于 __filename)
197 | - 可以通过检查 require.main.filename 来获取当前应用程序的入口点
198 |
199 | ```js
200 | // counter.js
201 | var counter = function (arr) {
202 | return "There are " + arr.length + " elements in array"
203 | }
204 |
205 | var adder = function (a, b) {
206 | return `the sum of the 2 numbers is ${a+b}`
207 | }
208 |
209 | var pi = 3.14
210 |
211 | // 只有一个时可以这样导入
212 | // module.exports = counter
213 |
214 | /*
215 | module.exports.counter = counter
216 | module.exports.adder = adder
217 | module.exports.pi = pi
218 | */
219 |
220 | module.exports = {
221 | counter: counter,
222 | adder: adder,
223 | pi: pi,
224 | }
225 | /* 对象可以简写
226 | module.exports = {
227 | counter,
228 | adder,
229 | pi,
230 | }
231 | */
232 |
233 | //p4.js
234 | var stuff = require('./count')
235 |
236 | console.log(stuff.counter(['ruby', 'nodejs', 'react']))
237 | console.log(stuff.adder(3, 2))
238 | console.log(stuff.pi)
239 | ```
240 |
241 | ## 5.事件 events
242 |
243 | - 多数 Node.js 核心 API 都采用异步事件驱动架构
244 | - 所有能触发事件的对象都是 EventEmitter 类的实例
245 | - 事件名称通常是驼峰式的字符串
246 |
247 | - 实践代码
248 |
249 | ```js
250 | var events = require('events')
251 | var util = require('util')
252 |
253 | // 事件 对象
254 | var myEmitter = new events.EventEmitter()
255 |
256 | // 绑定 事件名称 和 回调函数
257 | myEmitter.on('someEvent', function (message) {
258 | console.log(message)
259 | })
260 |
261 | // 触发实践,使用事件名称
262 | myEmitter.emit('someEvent', 'The event was emitted')
263 |
264 | // 创建对象
265 | var Person = function (name) {
266 | this.name = name
267 | }
268 |
269 | // 继承,让Person类具有事件对象的特性,绑定和触发事件
270 | util.inherits(Person, events.EventEmitter)
271 | // 新建对象
272 | var xiaoming = new Person('xiaoming')
273 | var lili = new Person('lili')
274 |
275 | var person = [xiaoming, lili]
276 |
277 | // 循环person数组,绑定事件
278 | person.forEach(function (person) {
279 | person.on('speak', function (message) {
280 | console.log(person.name + ' said: ' + message)
281 | })
282 | })
283 |
284 | // 触发事件
285 | xiaoming.emit('speak', 'hi')
286 | lili.emit('speak', 'I want a curry')
287 | ```
288 |
289 | ## 6.读写文件(同步和异步)
290 |
291 | ```js
292 | var fs = require('fs')
293 |
294 | // 同步读写文件,顺序执行,如果读取时间很长,会阻塞进程
295 | var readMe = fs.readFileSync('readMe.txt', 'utf8')
296 | fs.writeFileSync('writeMe.txt', readMe)
297 |
298 | console.log(readMe)
299 | console.log('finished sync')
300 |
301 | // 异步读写文件
302 | // 异步事件,Nodejs 维护一个事件队列,注册事件,完成后执行主线程
303 | // 当主线程空闲时,取出执行事件,从线程池中发起线程执行事件, 当事件执行完成后通知主线程。这就是异步高效的原因。
304 |
305 | var readMe = fs.readFile('readMe.txt', 'utf8', function (err, data) {
306 | fs.writeFile('writeMe.txt', data, function () {
307 | console.log('writeMe has finished')
308 | })
309 | })
310 |
311 | console.log('end')
312 | ```
313 |
314 | ## 7.创建和删除目录
315 |
316 | - [fs - 文件系统 API 文档](http://nodejs.cn/api/fs.html#fs_fs_unlink_path_callback)
317 |
318 | ```js
319 | var fs = require('fs')
320 |
321 | // 异步删除文件
322 | fs.unlink('writeMe.txt', function () {
323 | console.log('delete writeMe.txt file')
324 | })
325 |
326 | // 同步创建和删除目录
327 | fs.mkdirSync('stuff')
328 | fs.rmdirSync('stuff')
329 |
330 | // 异步
331 | fs.mkdir('stuff', function () {
332 | fs.readFile('readMe.txt', 'utf8', function (err, data) {
333 | fs.writeFile('./stuff/writeMe.txt', data, function () {
334 | console.log('copy successfully')
335 | })
336 | })
337 | })
338 | ```
339 |
340 | ## 8.流和管道
341 |
342 | - 流(stream)
343 | - 处理流式数据的抽象接口
344 | - stream 模块提供了一些基础的 API,用于构建实现了流接口的对象
345 | - 流可以是可读的、可写的、或是可读写的,所有的流都是 EventEmitter 的实例
346 | - 流处理数据通过缓存可以提高性能
347 |
348 | - 管道
349 | - 使用管道,代码量更少
350 | - myReadStream.pipe(myWriteStream)
351 |
352 | ```js
353 | var fs = require('fs')
354 |
355 | var myReadStream = fs.createReadStream(__dirname + '/readMe.txt')
356 | myReadStream.setEncoding('utf8')
357 | var myWriteStream = fs.createWriteStream(__dirname + '/writeMe.txt')
358 | var data = ''
359 |
360 | myReadStream.on('data', function (chunk) {
361 | console.log('new chunk received')
362 | // console.log(chunk)
363 | myWriteStream.write(chunk)
364 | })
365 |
366 | myReadStream.on('end', function () {
367 | console.log(data)
368 | })
369 |
370 | var writeData = 'hello world'
371 | myWriteStream.write(writeData)
372 | myWriteStream.end()
373 | myWriteStream.on('finish', function () {
374 | console.log('finished')
375 | })
376 |
377 | // 使用管道,代码量更少
378 | myReadStream.pipe(myWriteStream)
379 | ```
380 |
381 | ## 9.web 服务器 part1 介绍
382 |
383 | ```js
384 | var http = require('http')
385 |
386 | var server = http.createServer(function (req, res) {
387 | console.log('request received')
388 | res.writeHead(200, { 'Content-Type': 'text/plain' })
389 | // res.write('Hello from out application')
390 | // res.end()
391 | // 或
392 | res.end('Hello from out application')
393 | })
394 |
395 | server.listen(3000, '127.0.0.1')
396 | console.log('server started on http://127.0.0.1:3000')
397 | ```
398 |
399 | ## 10.web 服务器 part2 响应JSON
400 |
401 | - 响应JSON
402 |
403 | ```js
404 | var myObj = {
405 | name: 'able',
406 | job: 'programmer',
407 | age: 27
408 | }
409 | res.end(JSON.stringify(myObj))
410 | ```
411 |
412 | - [JSON 对象](https://wangdoc.com/javascript/stdlib/json.html)
413 | - 字符串必须使用双引号表示,不能使用单引号
414 | - 对象的键名必须放在双引号里面
415 | - 数组或对象最后一个成员的后面,不能加逗号
416 | - JSON对象是 JavaScript 的原生对象,用来处理 JSON 格式数据
417 | - JSON.stringify方法用于将一个值转为 JSON 字符串
418 | - JSON.parse方法用于将 JSON 字符串转换成对应的值
419 |
420 | ## 11.web 服务器 part3 响应HTML页面
421 |
422 | ```js
423 | var http = require('http')
424 | var fs = require('fs')
425 |
426 | var onRequest = function (req, res) {
427 | console.log('request received')
428 | res.writeHead(200, { 'Content-Type': 'text/html' })
429 | // res.writeHead(200, { 'Content-Type': 'text/plain' })
430 | var myReadStream = fs.createReadStream(__dirname + '/index.html', 'utf8')
431 | myReadStream.pipe(res)
432 | }
433 |
434 | var server = http.createServer(onRequest)
435 | server.listen(3000)
436 | console.log('server started on http://127.0.0.1:3000')
437 | ```
438 |
439 | ## 12.web 服务器 part4 用模块化思想组织代码
440 |
441 | - 代码封装成模块,方便统一管理和调用
442 |
443 | ```js
444 | // server.js
445 | var http = require('http')
446 | var fs = require('fs')
447 |
448 | function startServer() {
449 | var onRequest = function (req, res) {
450 | console.log('request received')
451 | res.writeHead(200, { 'Content-Type': 'text/html' })
452 |
453 | var myReadStream = fs.createReadStream(__dirname + '/index.html', 'utf8')
454 | myReadStream.pipe(res)
455 | }
456 | var server = http.createServer(onRequest)
457 | server.listen(3000)
458 | console.log('server started on http://127.0.0.1:3000')
459 | }
460 |
461 | module.exports.startServer = startServer
462 |
463 | // 调用
464 | var server = require('./server')
465 |
466 | server.startServer()
467 | ```
468 |
469 | ## 13.web 服务器 part5 路由
470 |
471 | - `console.dir(xx)` 查看对象的所有属性和方法
472 | - `req.url` 请求中包含url等属性
473 |
474 | ```js
475 | unction startServer() {
476 | var onRequest = function (req, res) {
477 | console.log('request received ' + req.url)
478 |
479 | if (req.url === '/' || req.url === '/home') {
480 | res.writeHead(200, { 'Content-Type': 'text/html' })
481 | fs.createReadStream(__dirname + '/index.html', 'utf8').pipe(res)
482 | } else if (req.url === '/review') {
483 | res.writeHead(200, { 'Content-Type': 'text/html' })
484 | fs.createReadStream(__dirname + '/review.html', 'utf8').pipe(res)
485 | } else if (req.url === '/api/v1/records') {
486 | res.writeHead(200, { 'Content-Type': 'application/json' })
487 | var jsonObj = {
488 | name: 'able'
489 | }
490 | res.end(JSON.stringify(jsonObj))
491 | } else {
492 | res.writeHead(200, { 'Content-Type': 'text/html' })
493 | fs.createReadStream(__dirname + '/404.html', 'utf8').pipe(res)
494 | }
495 | }
496 | var server = http.createServer(onRequest)
497 | server.listen(3000)
498 | console.log('server started on http://127.0.0.1:3000')
499 | }
500 | ```
501 |
502 | ## 14.web 服务器 part6 重构路由代码
503 |
504 | - 将路由、处理函数和主程序分离,单独存放
505 | - 分工明确,各司其职,方便管理
506 |
507 | ## 15.web 服务器 part7 使用 GET或 POST 请求 发送数据
508 |
509 | - [querystring - 查询字符串](http://nodejs.cn/api/querystring.html)
510 | - `var querystring = require('querystring')`
511 | - `querystring.parse(data)` 把一个 URL 查询字符串 str 解析成一个键值对的集合
512 |
513 | ```js
514 | // 接收请求数据,然后处理,查看request 类型
515 | var data = ""
516 | req.on("error", function (err) {
517 | console.error(err)
518 | }).on("data", function (chunk) {
519 | data += chunk
520 | }).on("end", function () {
521 | if (req.mothod === "POST") {
522 | if (data.length > 1e6) {
523 | req.connection.destroy() // 如果数据很大,就断开
524 | }
525 | route(handle, pathname, res, querystring.parse(data))
526 | } else {
527 | var params = url.parse(req.url, true).query
528 | route(handle, pathname, res, params)
529 | }
530 | })
531 | // 或者
532 | // var data = []
533 | // data.push(chunk)
534 | // data = Buffer.concat(data).toString()
535 | ```
536 |
537 | ## 16.包管理器 npm
538 |
539 | - [npm 官网](https://www.npmjs.com)
540 | - [搜索查看 express](https://www.npmjs.com/package/express)
541 |
542 | - `npm install -g xxx` 全局安装可执行文件,当作命令行工具
543 | - 使用国内源,解决慢的问题
544 |
545 | ```sh
546 | # Or alias it in .bashrc or .zshrc
547 | echo '\n#alias for npm\nalias npm="npm --registry=https://registry.npm.taobao.org \
548 | --cache=$HOME/.npm/.cache/npm \
549 | --disturl=https://npm.taobao.org/dist \
550 | --userconfig=$HOME/.npmrc"' >> ~/.zshrc && source ~/.zshrc
551 | ```
552 |
553 | - yarn 也是包管理器,更快下载速度
554 |
555 | ## 17.package.json 文件
556 |
557 | - 记录项目中使用的包名,发布时不用包内容了,只要名称就行
558 | - `npm init` 提问式初始化项目信息,生成`package.json`文件,-y 全部默认
559 | - `npm install --save xxx`安装的同时,将信息写入package.json
560 | - `npm install --save-dev xxx`安装的同时,将信息写入package.json中的dev开发依赖
561 | - `npm view moduleNames` 查看node模块的package.json文件夹
562 | - `npm run start` 启动包,执行 package.json scripts 中的 start 命令,还有 stop restart test
563 | - `npm install` 安装 package.json 中记录的包
564 |
565 | ## 18.nodemon监控文件并重启服务
566 |
567 | - nodemon 用来监视应用中的任何文件更改并自动重启服务
568 | - 非常适合用在开发环境中,方便啊,不用手动操作了
569 | - 全局安装 `npm install -g nodemon`
570 | - 本地安装 `npm install --save-dev nodemon`
571 | - 启动应用 `nodemon [your node app]`
572 | - 获取修改 package.json 中的启动脚本,添加`nodemon app.js`, 用 npm start 直接启动,方便
573 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | var server = require('./server')
2 | var router = require('./router')
3 | var handler = require('./handler')
4 |
5 | var handle = {}
6 | // key是路径,值是处理函数
7 | handle['/'] = handler.home
8 | handle['/home'] = handler.home
9 | handle['/review'] = handler.review
10 | handle['/api/v1/records'] = handler.api_records
11 |
12 | server.startServer(router.route, handle)
--------------------------------------------------------------------------------
/count.js:
--------------------------------------------------------------------------------
1 | var counter = function (arr) {
2 | return "There are " + arr.length + " elements in array"
3 | }
4 |
5 | var adder = function (a, b) {
6 | return `the sum of the 2 numbers is ${a+b}`
7 | }
8 |
9 | var pi = 3.14
10 |
11 | // 只有一个时可以这样导入
12 | // module.exports = counter
13 |
14 | /*
15 | module.exports.counter = counter
16 | module.exports.adder = adder
17 | module.exports.pi = pi
18 | */
19 |
20 | module.exports = {
21 | counter: counter,
22 | adder: adder,
23 | pi: pi,
24 | }
25 | /* 对象可以简写
26 | module.exports = {
27 | counter,
28 | adder,
29 | pi,
30 | }
31 | */
32 |
33 |
34 |
--------------------------------------------------------------------------------
/handler.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs')
2 |
3 | function home(res) {
4 | console.log('home')
5 | res.writeHead(200, { 'Content-Type': 'text/html' })
6 | fs.createReadStream(__dirname + '/index.html', 'utf8').pipe(res)
7 | }
8 |
9 | function review(res) {
10 | console.log('review')
11 | res.writeHead(200, { 'Content-Type': 'text/html' })
12 | fs.createReadStream(__dirname + '/review.html', 'utf8').pipe(res)
13 | }
14 |
15 | function api_records(res, params) {
16 | console.log('api_records')
17 | res.writeHead(200, { 'Content-Type': 'application/json' })
18 | res.end(JSON.stringify(params))
19 | }
20 |
21 | module.exports = {
22 | home: home,
23 | review: review,
24 | api_records: api_records
25 | }
--------------------------------------------------------------------------------
/hello-world-web.js:
--------------------------------------------------------------------------------
1 | const http = require('http')
2 |
3 | const hostname = '127.0.0.1'
4 | const port = 3000
5 |
6 | const server = http.createServer((req, res) => {
7 | res.statusCode = 200
8 | res.setHeader('Content-Type', 'text/plain')
9 | res.end('Hello World!')
10 | })
11 |
12 | server.listen(port, hostname, () => {
13 | console.log(`服务器运行在 http://${hostname}:${port}/`)
14 | })
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 | hello world
11 |
16 |
17 |
--------------------------------------------------------------------------------
/p11.js:
--------------------------------------------------------------------------------
1 | var http = require('http')
2 | var fs = require('fs')
3 |
4 | var onRequest = function (req, res) {
5 | console.log('request received')
6 | res.writeHead(200, { 'Content-Type': 'text/html' })
7 | // res.writeHead(200, { 'Content-Type': 'text/plain' })
8 | var myReadStream = fs.createReadStream(__dirname + '/index.html', 'utf8')
9 | myReadStream.pipe(res)
10 | }
11 |
12 | var server = http.createServer(onReque st)
13 | server.listen(3000)
14 | console.log('server started on http://127.0.0.1:3000')
15 |
16 |
--------------------------------------------------------------------------------
/p2.js:
--------------------------------------------------------------------------------
1 | console.log('hello world');
2 |
3 | setTimeout(function () {
4 | console.log("3 seconds have passed 2");
5 | }, 3000);
6 |
7 | // 箭头函数,es6的写法
8 | setTimeout(() => {
9 | console.log("3 seconds have passed 1");
10 | }, 3000);
11 |
12 | // 每间隔2秒不断执行
13 | setInterval(function () {
14 | console.log("2 seconds have passed");
15 | }, 2000);
16 |
17 | var time = 0
18 | var timer = setInterval(function () {
19 | time += 2;
20 | console.log(time + " seconds have passed");
21 | if (time > 6) {
22 | clearInterval(timer);
23 | console.log("clearInterval")
24 | }
25 | }, 2000)
26 |
27 | // 输出当前目录 和 带绝对路径的文件名
28 | console.log(__dirname)
29 | console.log(__filename)
30 |
31 | console.log('end')
32 | console.dir(global)
33 |
--------------------------------------------------------------------------------
/p3.js:
--------------------------------------------------------------------------------
1 | function sayHi() {
2 | console.log('Hi')
3 | }
4 |
5 | sayHi() // 调用函数
6 |
7 | // 将匿名函数赋给变量
8 | var sayBye = function (name) {
9 | console.log(name + ' Bye')
10 | }
11 |
12 | sayBye()
13 |
14 | // 第一个参数是函数
15 | function callFunction(fun, name) {
16 | fun(name)
17 | }
18 |
19 | callFunction(sayBye, 'able')
20 | // 或者
21 | callFunction(function (name) {
22 | console.log(name + ' Bye')
23 | }, 'able')
--------------------------------------------------------------------------------
/p4.js:
--------------------------------------------------------------------------------
1 | var stuff = require('./count')
2 |
3 | console.log(stuff.counter(['ruby', 'nodejs', 'react']))
4 | console.log(stuff.adder(3, 2))
5 | console.log(stuff.pi)
6 |
--------------------------------------------------------------------------------
/p5.js:
--------------------------------------------------------------------------------
1 | var events = require('events')
2 | var util = require('util')
3 |
4 | // 事件 对象
5 | var myEmitter = new events.EventEmitter()
6 |
7 | // 绑定 事件名称 和 回调函数
8 | myEmitter.on('someEvent', function (message) {
9 | console.log(message)
10 | })
11 |
12 | // 触发实践,使用事件名称
13 | myEmitter.emit('someEvent', 'The event was emitted')
14 |
15 | var Person = function (name) {
16 | this.name = name
17 | }
18 |
19 | // 继承,让Person类具有事件对象的特性,绑定和触发事件
20 | util.inherits(Person, events.EventEmitter)
21 | // 新建对象
22 | var xiaoming = new Person('xiaoming')
23 | var lili = new Person('lili')
24 |
25 | var person = [xiaoming, lili]
26 |
27 | // 循环person数组,绑定事件
28 | person.forEach(function (person) {
29 | person.on('speak', function (message) {
30 | console.log(person.name + ' said: ' + message)
31 | })
32 | })
33 |
34 | // 触发事件
35 | xiaoming.emit('speak', 'hi')
36 | lili.emit('speak', 'I want a curry')
--------------------------------------------------------------------------------
/p6.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs')
2 |
3 | // 同步读写文件,顺序执行,如果读取时间很长,会阻塞进程
4 | var readMe = fs.readFileSync('readMe.txt', 'utf8')
5 | fs.writeFileSync('writeMe.txt', readMe)
6 |
7 | console.log(readMe)
8 | console.log('finished sync')
9 |
10 | // 异步读写文件
11 | // 异步事件,Nodejs 维护一个事件队列,注册事件,完成后执行主线程
12 | // 当主线程空闲时,取出执行事件,从线程池中发起线程执行事件, 当事件执行完成后通知主线程。这就是异步高效的原因。
13 |
14 | var readMe = fs.readFile('readMe.txt', 'utf8', function (err, data) {
15 | fs.writeFile('writeMe.txt', data, function () {
16 | console.log('writeMe has finished')
17 | })
18 | })
19 |
20 | console.log('end')
21 |
--------------------------------------------------------------------------------
/p7.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs')
2 |
3 | // 异步删除文件
4 | fs.unlink('writeMe.txt', function () {
5 | console.log('delete writeMe.txt file')
6 | })
7 |
8 | // 同步创建和删除目录
9 | fs.mkdirSync('stuff')
10 | fs.rmdirSync('stuff')
11 |
12 | // 异步
13 | fs.mkdir('stuff', function () {
14 | fs.readFile('readMe.txt', 'utf8', function (err, data) {
15 | fs.writeFile('./stuff/writeMe.txt', data, function () {
16 | console.log('copy successfully')
17 | })
18 | })
19 | })
20 |
--------------------------------------------------------------------------------
/p8.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs')
2 |
3 | var myReadStream = fs.createReadStream(__dirname + '/readMe.txt')
4 | myReadStream.setEncoding('utf8')
5 | var myWriteStream = fs.createWriteStream(__dirname + '/writeMe.txt')
6 | var data = ''
7 |
8 | myReadStream.on('data', function (chunk) {
9 | console.log('new chunk received')
10 | // console.log(chunk)
11 | myWriteStream.write(chunk)
12 | })
13 |
14 | myReadStream.on('end', function () {
15 | console.log(data)
16 | })
17 |
18 | var writeData = 'hello world'
19 | myWriteStream.write(writeData)
20 | myWriteStream.end()
21 | myWriteStream.on('finish', function () {
22 | console.log('finished')
23 | })
24 |
25 |
26 | // 使用管道,代码量更少
27 | myReadStream.pipe(myWriteStream)
--------------------------------------------------------------------------------
/p9.js:
--------------------------------------------------------------------------------
1 | var http = require('http')
2 |
3 | var server = http.createServer(function (req, res) {
4 | console.log('request received')
5 | res.writeHead(200, { 'Content-Type': 'application/json' })
6 | var myObj = {
7 | name: 'able',
8 | job: 'programmer',
9 | age: 27
10 | }
11 | res.end(JSON.stringify(myObj))
12 | })
13 |
14 | server.listen(3000)
15 | console.log('server started on http://127.0.0.1:3000')
16 |
17 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hello-nodejs",
3 | "version": "1.0.0",
4 | "description": "轻松学 Node.js 基础篇 入门",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "nodemon app.js"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/able8/hello-nodejs.git"
13 | },
14 | "author": "",
15 | "license": "ISC",
16 | "bugs": {
17 | "url": "https://github.com/able8/hello-nodejs/issues"
18 | },
19 | "homepage": "https://github.com/able8/hello-nodejs#readme"
20 | }
21 |
--------------------------------------------------------------------------------
/readMe.txt:
--------------------------------------------------------------------------------
1 | you read me!
2 |
3 | # hello-nodejs
4 |
5 | 轻松学 Node.js 基础篇 入门
6 |
7 | 视频地址
8 |
9 | - [https://www.rails365.net](https://www.rails365.net/movies/qing-song-xue-nodejs-ji-chu-pian-1-ke-cheng-jie-shao-yu-kai-fa-huan-jing-da-jian)
10 | - [b站](https://www.bilibili.com/video/av21010015)
11 |
12 | 常用链接
13 |
14 | - [Node.js 官网](https://nodejs.org/zh-cn/)
15 | - [Node.js 中文网](http://nodejs.cn)
16 | - [CNode:Node.js专业中文社区](https://cnodejs.org)
17 |
18 | 看视频整理要点笔记:
19 |
20 | ---
21 |
22 | - [hello-nodejs](#hello-nodejs)
23 | - [1.课程介绍与开发环境搭建](#1%E8%AF%BE%E7%A8%8B%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA)
24 | - [2.全局对象](#2%E5%85%A8%E5%B1%80%E5%AF%B9%E8%B1%A1)
25 |
26 | ---
27 |
28 | ## 1.课程介绍与开发环境搭建
29 |
30 | - 主要包括
31 | - nodejs 基础知识
32 | - web 服务器
33 | - 异步 同步 阻塞 非阻塞
34 |
35 | - 课程基础
36 | - javascript 基础
37 | - html 基础
38 | - 命令行基础
39 |
40 | - Node.js 介绍
41 | - Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境
42 | - Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效
43 | - Node.js 的包管理器 npm,是全球最大的开源库生态系统
44 | - javascript 是脚本语言,需要解析器才能执行,浏览器就充当了解析器
45 | - 在Chrome中,解析器就是 V8 引擎,将 javascript 转换成 机器码
46 | - V8 引擎是开源的,由 C++ 语言编写,性能高
47 | - Node.js 高性能,事件驱动,非阻塞,生态圈很好
48 |
49 | - Node.js 安装
50 | - [官网](https://nodejs.org/zh-cn/) 下载安装即可,很小不到20M!
51 | - 验证是否成功,命令行输入 `node -v` 显示版本号如 `v8.11.4`
52 | - 按提示升级 npm,Update available 5.6.0 → 6.4.1, `npm i -g npm`
53 | - macOS 安装完提示如下
54 |
55 | ```sh
56 | This package has installed:
57 | • Node.js v8.11.4 to /usr/local/bin/node
58 | • npm v5.6.0 to /usr/local/bin/npm
59 | Make sure that /usr/local/bin is in your $PATH.
60 | ```
61 |
62 | - Node.js 用途
63 |
64 | - javascript 运行环境
65 | - 操作文件(grunt gulp webpack)
66 | - 操作数据库
67 | - 写后端 api
68 | - 命令行工具
69 | - web 开发
70 | - 聊天室
71 |
72 | - JavaScript 语句后应该加分号么?
73 | - [知乎讨论](https://www.zhihu.com/question/20298345)
74 | - 代码风格而已,没有定论
75 | - 少分号更易读,不累
76 | - 必须加分号情况很少见:一行开头是括号`(`或者方括号`[`的时候加上分号就可以了,其他时候都不要
77 | - 如果下一行的行首是`( [ / + -`之一的话,js不会自动在上一行句尾加上分号
78 |
79 | ## 2.全局对象
80 |
81 | - 全局对象
82 | - 不用导入,直接使用的对象
83 | - [官方文档](http://nodejs.cn/api/globals.html#globals_global_objects)
84 | - Buffer 类,用于处理二进制数据
85 | - console,用于打印 stdout 和 stderr
86 | - global, 全局的命名空间对象
87 | - process,进程对象
88 | - setTimeout(callback, delay[, ...args])
89 | - setInterval(callback, delay[, ...args])
90 | - setImmediate(callback[, ...args])
91 | - clearTimeout(timeoutObject)
92 | - clearInterval(intervalObject)
93 | - clearImmediate(immediateObject)
94 |
95 | - 以下变量虽然看起来像全局变量,但实际上不是
96 | - 全局变量在所有模块中均可使用
97 | - 以下对象作用域只在模块内,详见 [module文档](http://nodejs.cn/api/modules.html):
98 | - __dirname
99 | - __filename
100 | - exports
101 | - module
102 | - require()
103 |
104 | - 运行 `.js` 脚本文件
105 | - `node app` 或者 `node app.js`
106 |
107 | - 实践代码
108 |
109 | ```js
110 | console.log('hello world');
111 |
112 | setTimeout(function () {
113 | console.log("3 seconds have passed 2");
114 | }, 3000);
115 |
116 | // 箭头函数,es6的写法
117 | setTimeout(() => {
118 | console.log("3 seconds have passed 1");
119 | }, 3000);
120 |
121 | // 每间隔2秒不断执行
122 | setInterval(function () {
123 | console.log("2 seconds have passed");
124 | }, 2000);
125 |
126 |
127 | var time = 0
128 | var timer = setInterval(function () {
129 | time += 2;
130 | console.log(time + " seconds have passed");
131 | if (time > 6) {
132 | clearInterval(timer);
133 | console.log("clearInterval")
134 | }
135 | }, 2000)
136 |
137 | // 输出当前目录 和 带绝对路径的文件名
138 | console.log(__dirname)
139 | console.log(__filename)
140 |
141 | console.log('end')
142 | console.dir(global)
143 | ```
144 |
145 | ## 3.回调函数
146 |
147 | ```js
148 | function sayHi() {
149 | console.log('Hi')
150 | }
151 |
152 | sayHi() // 调用函数
153 |
154 | // 将匿名函数赋给变量
155 | var sayBye = function (name) {
156 | console.log(name + ' Bye')
157 | }
158 |
159 | sayBye()
160 |
161 | // 第一个参数是函数
162 | function callFunction(fun, name) {
163 | fun(name)
164 | }
165 |
166 | callFunction(sayBye, 'able')
167 | // 或者
168 | callFunction(function (name) {
169 | console.log(name + ' Bye')
170 | }, 'able')
171 | ```
172 |
173 | ## 4.模块
174 |
175 | - module 对象
176 | - 每个文件都被视为独立的模块
177 | - 每个模块中,module 指向表示当前模块的对象的引用
178 | - module 实际上不是全局的,而是每个模块本地的
179 | - module.exports 导出模块内的对象,方便其他对象引用
180 | - require() 引入模块
181 | - 当 Node.js 直接运行一个文件时,require.main 会被设为它的 module
182 | - 可以通过 require.main === module 来判断一个文件是否被直接运行
183 | - module 提供了一个 filename 属性(通常等同于 __filename)
184 | - 可以通过检查 require.main.filename 来获取当前应用程序的入口点
185 |
186 | ```js
187 | // counter.js
188 | var counter = function (arr) {
189 | return "There are " + arr.length + " elements in array"
190 | }
191 |
192 | var adder = function (a, b) {
193 | return `the sum of the 2 numbers is ${a+b}`
194 | }
195 |
196 | var pi = 3.14
197 |
198 | // 只有一个时可以这样导入
199 | // module.exports = counter
200 |
201 | /*
202 | module.exports.counter = counter
203 | module.exports.adder = adder
204 | module.exports.pi = pi
205 | */
206 |
207 | module.exports = {
208 | counter: counter,
209 | adder: adder,
210 | pi: pi,
211 | }
212 | /* 对象可以简写
213 | module.exports = {
214 | counter,
215 | adder,
216 | pi,
217 | }
218 | */
219 |
220 | //p4.js
221 | var stuff = require('./count')
222 |
223 | console.log(stuff.counter(['ruby', 'nodejs', 'react']))
224 | console.log(stuff.adder(3, 2))
225 | console.log(stuff.pi)
226 | ```
227 |
228 | ## 5.事件 events
229 |
230 | - 多数 Node.js 核心 API 都采用异步事件驱动架构
231 | - 所有能触发事件的对象都是 EventEmitter 类的实例
232 | - 事件名称通常是驼峰式的字符串
233 |
234 | - 实践代码
235 |
236 | ```js
237 | var events = require('events')
238 | var util = require('util')
239 |
240 | // 事件 对象
241 | var myEmitter = new events.EventEmitter()
242 |
243 | // 绑定 事件名称 和 回调函数
244 | myEmitter.on('someEvent', function (message) {
245 | console.log(message)
246 | })
247 |
248 | // 触发实践,使用事件名称
249 | myEmitter.emit('someEvent', 'The event was emitted')
250 |
251 | // 创建对象
252 | var Person = function (name) {
253 | this.name = name
254 | }
255 |
256 | // 继承,让Person类具有事件对象的特性,绑定和触发事件
257 | util.inherits(Person, events.EventEmitter)
258 | // 新建对象
259 | var xiaoming = new Person('xiaoming')
260 | var lili = new Person('lili')
261 |
262 | var person = [xiaoming, lili]
263 |
264 | // 循环person数组,绑定事件
265 | person.forEach(function (person) {
266 | person.on('speak', function (message) {
267 | console.log(person.name + ' said: ' + message)
268 | })
269 | })
270 |
271 | // 触发事件
272 | xiaoming.emit('speak', 'hi')
273 | lili.emit('speak', 'I want a curry')
274 | ```
275 |
276 | ## 6.读写文件(同步和异步)
277 |
278 | ```js
279 | var fs = require('fs')
280 |
281 | // 同步读写文件,顺序执行,如果读取时间很长,会阻塞进程
282 | var readMe = fs.readFileSync('readMe.txt', 'utf8')
283 | fs.writeFileSync('writeMe.txt', readMe)
284 |
285 | console.log(readMe)
286 | console.log('finished sync')
287 |
288 | // 异步读写文件
289 | // 异步事件,Nodejs 维护一个事件队列,注册事件,完成后执行主线程
290 | // 当主线程空闲时,取出执行事件,从线程池中发起线程执行事件, 当事件执行完成后通知主线程。这就是异步高效的原因。
291 |
292 | var readMe = fs.readFile('readMe.txt', 'utf8', function (err, data) {
293 | fs.writeFile('writeMe.txt', data, function () {
294 | console.log('writeMe has finished')
295 | })
296 | })
297 |
298 | console.log('end')
299 | ```
300 |
301 | ## 7.创建和删除目录
302 |
303 | - [ fs - 文件系统 API 文档](http://nodejs.cn/api/fs.html#fs_fs_unlink_path_callback)
304 |
305 | ```js
306 | var fs = require('fs')
307 |
308 | // 异步删除文件
309 | fs.unlink('writeMe.txt', function () {
310 | console.log('delete writeMe.txt file')
311 | })
312 |
313 | // 同步创建和删除目录
314 | fs.mkdirSync('stuff')
315 | fs.rmdirSync('stuff')
316 |
317 | // 异步
318 | fs.mkdir('stuff', function () {
319 | fs.readFile('readMe.txt', 'utf8', function (err, data) {
320 | fs.writeFile('./stuff/writeMe.txt', data, function () {
321 | console.log('copy successfully')
322 | })
323 | })
324 | })
325 | ```
326 |
327 | ## 8.流和管道
328 |
329 | - 流(stream)
330 | - 处理流式数据的抽象接口
331 | - stream 模块提供了一些基础的 API,用于构建实现了流接口的对象
332 | - 流可以是可读的、可写的、或是可读写的,所有的流都是 EventEmitter 的实例
333 | - 流处理数据通过缓存可以提高性能
334 |
335 | # hello-nodejs
336 |
337 | 轻松学 Node.js 基础篇 入门
338 |
339 | 视频地址
340 |
341 | - [https://www.rails365.net](https://www.rails365.net/movies/qing-song-xue-nodejs-ji-chu-pian-1-ke-cheng-jie-shao-yu-kai-fa-huan-jing-da-jian)
342 | - [b站](https://www.bilibili.com/video/av21010015)
343 |
344 | 常用链接
345 |
346 | - [Node.js 官网](https://nodejs.org/zh-cn/)
347 | - [Node.js 中文网](http://nodejs.cn)
348 | - [CNode:Node.js专业中文社区](https://cnodejs.org)
349 |
350 | 看视频整理要点笔记:
351 |
352 | ---
353 |
354 | - [hello-nodejs](#hello-nodejs)
355 | - [1.课程介绍与开发环境搭建](#1%E8%AF%BE%E7%A8%8B%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA)
356 | - [2.全局对象](#2%E5%85%A8%E5%B1%80%E5%AF%B9%E8%B1%A1)
357 |
358 | ---
359 |
360 | ## 1.课程介绍与开发环境搭建
361 |
362 | - 主要包括
363 | - nodejs 基础知识
364 | - web 服务器
365 | - 异步 同步 阻塞 非阻塞
366 |
367 | - 课程基础
368 | - javascript 基础
369 | - html 基础
370 | - 命令行基础
371 |
372 | - Node.js 介绍
373 | - Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境
374 | - Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效
375 | - Node.js 的包管理器 npm,是全球最大的开源库生态系统
376 | - javascript 是脚本语言,需要解析器才能执行,浏览器就充当了解析器
377 | - 在Chrome中,解析器就是 V8 引擎,将 javascript 转换成 机器码
378 | - V8 引擎是开源的,由 C++ 语言编写,性能高
379 | - Node.js 高性能,事件驱动,非阻塞,生态圈很好
380 |
381 | - Node.js 安装
382 | - [官网](https://nodejs.org/zh-cn/) 下载安装即可,很小不到20M!
383 | - 验证是否成功,命令行输入 `node -v` 显示版本号如 `v8.11.4`
384 | - 按提示升级 npm,Update available 5.6.0 → 6.4.1, `npm i -g npm`
385 | - macOS 安装完提示如下
386 |
387 | ```sh
388 | This package has installed:
389 | • Node.js v8.11.4 to /usr/local/bin/node
390 | • npm v5.6.0 to /usr/local/bin/npm
391 | Make sure that /usr/local/bin is in your $PATH.
392 | ```
393 |
394 | - Node.js 用途
395 |
396 | - javascript 运行环境
397 | - 操作文件(grunt gulp webpack)
398 | - 操作数据库
399 | - 写后端 api
400 | - 命令行工具
401 | - web 开发
402 | - 聊天室
403 |
404 | - JavaScript 语句后应该加分号么?
405 | - [知乎讨论](https://www.zhihu.com/question/20298345)
406 | - 代码风格而已,没有定论
407 | - 少分号更易读,不累
408 | - 必须加分号情况很少见:一行开头是括号`(`或者方括号`[`的时候加上分号就可以了,其他时候都不要
409 | - 如果下一行的行首是`( [ / + -`之一的话,js不会自动在上一行句尾加上分号
410 |
411 | ## 2.全局对象
412 |
413 | - 全局对象
414 | - 不用导入,直接使用的对象
415 | - [官方文档](http://nodejs.cn/api/globals.html#globals_global_objects)
416 | - Buffer 类,用于处理二进制数据
417 | - console,用于打印 stdout 和 stderr
418 | - global, 全局的命名空间对象
419 | - process,进程对象
420 | - setTimeout(callback, delay[, ...args])
421 | - setInterval(callback, delay[, ...args])
422 | - setImmediate(callback[, ...args])
423 | - clearTimeout(timeoutObject)
424 | - clearInterval(intervalObject)
425 | - clearImmediate(immediateObject)
426 |
427 | - 以下变量虽然看起来像全局变量,但实际上不是
428 | - 全局变量在所有模块中均可使用
429 | - 以下对象作用域只在模块内,详见 [module文档](http://nodejs.cn/api/modules.html):
430 | - __dirname
431 | - __filename
432 | - exports
433 | - module
434 | - require()
435 |
436 | - 运行 `.js` 脚本文件
437 | - `node app` 或者 `node app.js`
438 |
439 | - 实践代码
440 |
441 | ```js
442 | console.log('hello world');
443 |
444 | setTimeout(function () {
445 | console.log("3 seconds have passed 2");
446 | }, 3000);
447 |
448 | // 箭头函数,es6的写法
449 | setTimeout(() => {
450 | console.log("3 seconds have passed 1");
451 | }, 3000);
452 |
453 | // 每间隔2秒不断执行
454 | setInterval(function () {
455 | console.log("2 seconds have passed");
456 | }, 2000);
457 |
458 |
459 | var time = 0
460 | var timer = setInterval(function () {
461 | time += 2;
462 | console.log(time + " seconds have passed");
463 | if (time > 6) {
464 | clearInterval(timer);
465 | console.log("clearInterval")
466 | }
467 | }, 2000)
468 |
469 | // 输出当前目录 和 带绝对路径的文件名
470 | console.log(__dirname)
471 | console.log(__filename)
472 |
473 | console.log('end')
474 | console.dir(global)
475 | ```
476 |
477 | ## 3.回调函数
478 |
479 | ```js
480 | function sayHi() {
481 | console.log('Hi')
482 | }
483 |
484 | sayHi() // 调用函数
485 |
486 | // 将匿名函数赋给变量
487 | var sayBye = function (name) {
488 | console.log(name + ' Bye')
489 | }
490 |
491 | sayBye()
492 |
493 | // 第一个参数是函数
494 | function callFunction(fun, name) {
495 | fun(name)
496 | }
497 |
498 | callFunction(sayBye, 'able')
499 | // 或者
500 | callFunction(function (name) {
501 | console.log(name + ' Bye')
502 | }, 'able')
503 | ```
504 |
505 | ## 4.模块
506 |
507 | - module 对象
508 | - 每个文件都被视为独立的模块
509 | - 每个模块中,module 指向表示当前模块的对象的引用
510 | - module 实际上不是全局的,而是每个模块本地的
511 | - module.exports 导出模块内的对象,方便其他对象引用
512 | - require() 引入模块
513 | - 当 Node.js 直接运行一个文件时,require.main 会被设为它的 module
514 | - 可以通过 require.main === module 来判断一个文件是否被直接运行
515 | - module 提供了一个 filename 属性(通常等同于 __filename)
516 | - 可以通过检查 require.main.filename 来获取当前应用程序的入口点
517 |
518 | ```js
519 | // counter.js
520 | var counter = function (arr) {
521 | return "There are " + arr.length + " elements in array"
522 | }
523 |
524 | var adder = function (a, b) {
525 | return `the sum of the 2 numbers is ${a+b}`
526 | }
527 |
528 | var pi = 3.14
529 |
530 | // 只有一个时可以这样导入
531 | // module.exports = counter
532 |
533 | /*
534 | module.exports.counter = counter
535 | module.exports.adder = adder
536 | module.exports.pi = pi
537 | */
538 |
539 | module.exports = {
540 | counter: counter,
541 | adder: adder,
542 | pi: pi,
543 | }
544 | /* 对象可以简写
545 | module.exports = {
546 | counter,
547 | adder,
548 | pi,
549 | }
550 | */
551 |
552 | //p4.js
553 | var stuff = require('./count')
554 |
555 | console.log(stuff.counter(['ruby', 'nodejs', 'react']))
556 | console.log(stuff.adder(3, 2))
557 | console.log(stuff.pi)
558 | ```
559 |
560 | ## 5.事件 events
561 |
562 | - 多数 Node.js 核心 API 都采用异步事件驱动架构
563 | - 所有能触发事件的对象都是 EventEmitter 类的实例
564 | - 事件名称通常是驼峰式的字符串
565 |
566 | - 实践代码
567 |
568 | ```js
569 | var events = require('events')
570 | var util = require('util')
571 |
572 | // 事件 对象
573 | var myEmitter = new events.EventEmitter()
574 |
575 | // 绑定 事件名称 和 回调函数
576 | myEmitter.on('someEvent', function (message) {
577 | console.log(message)
578 | })
579 |
580 | // 触发实践,使用事件名称
581 | myEmitter.emit('someEvent', 'The event was emitted')
582 |
583 | // 创建对象
584 | var Person = function (name) {
585 | this.name = name
586 | }
587 |
588 | // 继承,让Person类具有事件对象的特性,绑定和触发事件
589 | util.inherits(Person, events.EventEmitter)
590 | // 新建对象
591 | var xiaoming = new Person('xiaoming')
592 | var lili = new Person('lili')
593 |
594 | var person = [xiaoming, lili]
595 |
596 | // 循环person数组,绑定事件
597 | person.forEach(function (person) {
598 | person.on('speak', function (message) {
599 | console.log(person.name + ' said: ' + message)
600 | })
601 | })
602 |
603 | // 触发事件
604 | xiaoming.emit('speak', 'hi')
605 | lili.emit('speak', 'I want a curry')
606 | ```
607 |
608 | ## 6.读写文件(同步和异步)
609 |
610 | ```js
611 | var fs = require('fs')
612 |
613 | // 同步读写文件,顺序执行,如果读取时间很长,会阻塞进程
614 | var readMe = fs.readFileSync('readMe.txt', 'utf8')
615 | fs.writeFileSync('writeMe.txt', readMe)
616 |
617 | console.log(readMe)
618 | console.log('finished sync')
619 |
620 | // 异步读写文件
621 | // 异步事件,Nodejs 维护一个事件队列,注册事件,完成后执行主线程
622 | // 当主线程空闲时,取出执行事件,从线程池中发起线程执行事件, 当事件执行完成后通知主线程。这就是异步高效的原因。
623 |
624 | var readMe = fs.readFile('readMe.txt', 'utf8', function (err, data) {
625 | fs.writeFile('writeMe.txt', data, function () {
626 | console.log('writeMe has finished')
627 | })
628 | })
629 |
630 | console.log('end')
631 | ```
632 |
633 | ## 7.创建和删除目录
634 |
635 | - [ fs - 文件系统 API 文档](http://nodejs.cn/api/fs.html#fs_fs_unlink_path_callback)
636 |
637 | ```js
638 | var fs = require('fs')
639 |
640 | // 异步删除文件
641 | fs.unlink('writeMe.txt', function () {
642 | console.log('delete writeMe.txt file')
643 | })
644 |
645 | // 同步创建和删除目录
646 | fs.mkdirSync('stuff')
647 | fs.rmdirSync('stuff')
648 |
649 | // 异步
650 | fs.mkdir('stuff', function () {
651 | fs.readFile('readMe.txt', 'utf8', function (err, data) {
652 | fs.writeFile('./stuff/writeMe.txt', data, function () {
653 | console.log('copy successfully')
654 | })
655 | })
656 | })
657 | ```
658 |
659 | ## 8.流和管道
660 |
661 | - 流(stream)
662 | - 处理流式数据的抽象接口
663 | - stream 模块提供了一些基础的 API,用于构建实现了流接口的对象
664 | - 流可以是可读的、可写的、或是可读写的,所有的流都是 EventEmitter 的实例
665 | - 流处理数据通过缓存可以提高性能
666 | # hello-nodejs
667 |
668 | 轻松学 Node.js 基础篇 入门
669 |
670 | 视频地址
671 |
672 | - [https://www.rails365.net](https://www.rails365.net/movies/qing-song-xue-nodejs-ji-chu-pian-1-ke-cheng-jie-shao-yu-kai-fa-huan-jing-da-jian)
673 | - [b站](https://www.bilibili.com/video/av21010015)
674 |
675 | 常用链接
676 |
677 | - [Node.js 官网](https://nodejs.org/zh-cn/)
678 | - [Node.js 中文网](http://nodejs.cn)
679 | - [CNode:Node.js专业中文社区](https://cnodejs.org)
680 |
681 | 看视频整理要点笔记:
682 |
683 | ---
684 |
685 | - [hello-nodejs](#hello-nodejs)
686 | - [1.课程介绍与开发环境搭建](#1%E8%AF%BE%E7%A8%8B%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA)
687 | - [2.全局对象](#2%E5%85%A8%E5%B1%80%E5%AF%B9%E8%B1%A1)
688 |
689 | ---
690 |
691 | ## 1.课程介绍与开发环境搭建
692 |
693 | - 主要包括
694 | - nodejs 基础知识
695 | - web 服务器
696 | - 异步 同步 阻塞 非阻塞
697 |
698 | - 课程基础
699 | - javascript 基础
700 | - html 基础
701 | - 命令行基础
702 |
703 | - Node.js 介绍
704 | - Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境
705 | - Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效
706 | - Node.js 的包管理器 npm,是全球最大的开源库生态系统
707 | - javascript 是脚本语言,需要解析器才能执行,浏览器就充当了解析器
708 | - 在Chrome中,解析器就是 V8 引擎,将 javascript 转换成 机器码
709 | - V8 引擎是开源的,由 C++ 语言编写,性能高
710 | - Node.js 高性能,事件驱动,非阻塞,生态圈很好
711 |
712 | - Node.js 安装
713 | - [官网](https://nodejs.org/zh-cn/) 下载安装即可,很小不到20M!
714 | - 验证是否成功,命令行输入 `node -v` 显示版本号如 `v8.11.4`
715 | - 按提示升级 npm,Update available 5.6.0 → 6.4.1, `npm i -g npm`
716 | - macOS 安装完提示如下
717 |
718 | ```sh
719 | This package has installed:
720 | • Node.js v8.11.4 to /usr/local/bin/node
721 | • npm v5.6.0 to /usr/local/bin/npm
722 | Make sure that /usr/local/bin is in your $PATH.
723 | ```
724 |
725 | - Node.js 用途
726 |
727 | - javascript 运行环境
728 | - 操作文件(grunt gulp webpack)
729 | - 操作数据库
730 | - 写后端 api
731 | - 命令行工具
732 | - web 开发
733 | - 聊天室
734 |
735 | - JavaScript 语句后应该加分号么?
736 | - [知乎讨论](https://www.zhihu.com/question/20298345)
737 | - 代码风格而已,没有定论
738 | - 少分号更易读,不累
739 | - 必须加分号情况很少见:一行开头是括号`(`或者方括号`[`的时候加上分号就可以了,其他时候都不要
740 | - 如果下一行的行首是`( [ / + -`之一的话,js不会自动在上一行句尾加上分号
741 |
742 | ## 2.全局对象
743 |
744 | - 全局对象
745 | - 不用导入,直接使用的对象
746 | - [官方文档](http://nodejs.cn/api/globals.html#globals_global_objects)
747 | - Buffer 类,用于处理二进制数据
748 | - console,用于打印 stdout 和 stderr
749 | - global, 全局的命名空间对象
750 | - process,进程对象
751 | - setTimeout(callback, delay[, ...args])
752 | - setInterval(callback, delay[, ...args])
753 | - setImmediate(callback[, ...args])
754 | - clearTimeout(timeoutObject)
755 | - clearInterval(intervalObject)
756 | - clearImmediate(immediateObject)
757 |
758 | - 以下变量虽然看起来像全局变量,但实际上不是
759 | - 全局变量在所有模块中均可使用
760 | - 以下对象作用域只在模块内,详见 [module文档](http://nodejs.cn/api/modules.html):
761 | - __dirname
762 | - __filename
763 | - exports
764 | - module
765 | - require()
766 |
767 | - 运行 `.js` 脚本文件
768 | - `node app` 或者 `node app.js`
769 |
770 | - 实践代码
771 |
772 | ```js
773 | console.log('hello world');
774 |
775 | setTimeout(function () {
776 | console.log("3 seconds have passed 2");
777 | }, 3000);
778 |
779 | // 箭头函数,es6的写法
780 | setTimeout(() => {
781 | console.log("3 seconds have passed 1");
782 | }, 3000);
783 |
784 | // 每间隔2秒不断执行
785 | setInterval(function () {
786 | console.log("2 seconds have passed");
787 | }, 2000);
788 |
789 |
790 | var time = 0
791 | var timer = setInterval(function () {
792 | time += 2;
793 | console.log(time + " seconds have passed");
794 | if (time > 6) {
795 | clearInterval(timer);
796 | console.log("clearInterval")
797 | }
798 | }, 2000)
799 |
800 | // 输出当前目录 和 带绝对路径的文件名
801 | console.log(__dirname)
802 | console.log(__filename)
803 |
804 | console.log('end')
805 | console.dir(global)
806 | ```
807 |
808 | ## 3.回调函数
809 |
810 | ```js
811 | function sayHi() {
812 | console.log('Hi')
813 | }
814 |
815 | sayHi() // 调用函数
816 |
817 | // 将匿名函数赋给变量
818 | var sayBye = function (name) {
819 | console.log(name + ' Bye')
820 | }
821 |
822 | sayBye()
823 |
824 | // 第一个参数是函数
825 | function callFunction(fun, name) {
826 | fun(name)
827 | }
828 |
829 | callFunction(sayBye, 'able')
830 | // 或者
831 | callFunction(function (name) {
832 | console.log(name + ' Bye')
833 | }, 'able')
834 | ```
835 |
836 | ## 4.模块
837 |
838 | - module 对象
839 | - 每个文件都被视为独立的模块
840 | - 每个模块中,module 指向表示当前模块的对象的引用
841 | - module 实际上不是全局的,而是每个模块本地的
842 | - module.exports 导出模块内的对象,方便其他对象引用
843 | - require() 引入模块
844 | - 当 Node.js 直接运行一个文件时,require.main 会被设为它的 module
845 | - 可以通过 require.main === module 来判断一个文件是否被直接运行
846 | - module 提供了一个 filename 属性(通常等同于 __filename)
847 | - 可以通过检查 require.main.filename 来获取当前应用程序的入口点
848 |
849 | ```js
850 | // counter.js
851 | var counter = function (arr) {
852 | return "There are " + arr.length + " elements in array"
853 | }
854 |
855 | var adder = function (a, b) {
856 | return `the sum of the 2 numbers is ${a+b}`
857 | }
858 |
859 | var pi = 3.14
860 |
861 | // 只有一个时可以这样导入
862 | // module.exports = counter
863 |
864 | /*
865 | module.exports.counter = counter
866 | module.exports.adder = adder
867 | module.exports.pi = pi
868 | */
869 |
870 | module.exports = {
871 | counter: counter,
872 | adder: adder,
873 | pi: pi,
874 | }
875 | /* 对象可以简写
876 | module.exports = {
877 | counter,
878 | adder,
879 | pi,
880 | }
881 | */
882 |
883 | //p4.js
884 | var stuff = require('./count')
885 |
886 | console.log(stuff.counter(['ruby', 'nodejs', 'react']))
887 | console.log(stuff.adder(3, 2))
888 | console.log(stuff.pi)
889 | ```
890 |
891 | ## 5.事件 events
892 |
893 | - 多数 Node.js 核心 API 都采用异步事件驱动架构
894 | - 所有能触发事件的对象都是 EventEmitter 类的实例
895 | - 事件名称通常是驼峰式的字符串
896 |
897 | - 实践代码
898 |
899 | ```js
900 | var events = require('events')
901 | var util = require('util')
902 |
903 | // 事件 对象
904 | var myEmitter = new events.EventEmitter()
905 |
906 | // 绑定 事件名称 和 回调函数
907 | myEmitter.on('someEvent', function (message) {
908 | console.log(message)
909 | })
910 |
911 | // 触发实践,使用事件名称
912 | myEmitter.emit('someEvent', 'The event was emitted')
913 |
914 | // 创建对象
915 | var Person = function (name) {
916 | this.name = name
917 | }
918 |
919 | // 继承,让Person类具有事件对象的特性,绑定和触发事件
920 | util.inherits(Person, events.EventEmitter)
921 | // 新建对象
922 | var xiaoming = new Person('xiaoming')
923 | var lili = new Person('lili')
924 |
925 | var person = [xiaoming, lili]
926 |
927 | // 循环person数组,绑定事件
928 | person.forEach(function (person) {
929 | person.on('speak', function (message) {
930 | console.log(person.name + ' said: ' + message)
931 | })
932 | })
933 |
934 | // 触发事件
935 | xiaoming.emit('speak', 'hi')
936 | lili.emit('speak', 'I want a curry')
937 | ```
938 |
939 | ## 6.读写文件(同步和异步)
940 |
941 | ```js
942 | var fs = require('fs')
943 |
944 | // 同步读写文件,顺序执行,如果读取时间很长,会阻塞进程
945 | var readMe = fs.readFileSync('readMe.txt', 'utf8')
946 | fs.writeFileSync('writeMe.txt', readMe)
947 |
948 | console.log(readMe)
949 | console.log('finished sync')
950 |
951 | // 异步读写文件
952 | // 异步事件,Nodejs 维护一个事件队列,注册事件,完成后执行主线程
953 | // 当主线程空闲时,取出执行事件,从线程池中发起线程执行事件, 当事件执行完成后通知主线程。这就是异步高效的原因。
954 |
955 | var readMe = fs.readFile('readMe.txt', 'utf8', function (err, data) {
956 | fs.writeFile('writeMe.txt', data, function () {
957 | console.log('writeMe has finished')
958 | })
959 | })
960 |
961 | console.log('end')
962 | ```
963 |
964 | ## 7.创建和删除目录
965 |
966 | - [ fs - 文件系统 API 文档](http://nodejs.cn/api/fs.html#fs_fs_unlink_path_callback)
967 |
968 | ```js
969 | var fs = require('fs')
970 |
971 | // 异步删除文件
972 | fs.unlink('writeMe.txt', function () {
973 | console.log('delete writeMe.txt file')
974 | })
975 |
976 | // 同步创建和删除目录
977 | fs.mkdirSync('stuff')
978 | fs.rmdirSync('stuff')
979 |
980 | // 异步
981 | fs.mkdir('stuff', function () {
982 | fs.readFile('readMe.txt', 'utf8', function (err, data) {
983 | fs.writeFile('./stuff/writeMe.txt', data, function () {
984 | console.log('copy successfully')
985 | })
986 | })
987 | })
988 | ```
989 |
990 | ## 8.流和管道
991 |
992 | - 流(stream)
993 | - 处理流式数据的抽象接口
994 | - stream 模块提供了一些基础的 API,用于构建实现了流接口的对象
995 | - 流可以是可读的、可写的、或是可读写的,所有的流都是 EventEmitter 的实例
996 | - 流处理数据通过缓存可以提高性能
997 | # hello-nodejs
998 |
999 | 轻松学 Node.js 基础篇 入门
1000 |
1001 | 视频地址
1002 |
1003 | - [https://www.rails365.net](https://www.rails365.net/movies/qing-song-xue-nodejs-ji-chu-pian-1-ke-cheng-jie-shao-yu-kai-fa-huan-jing-da-jian)
1004 | - [b站](https://www.bilibili.com/video/av21010015)
1005 |
1006 | 常用链接
1007 |
1008 | - [Node.js 官网](https://nodejs.org/zh-cn/)
1009 | - [Node.js 中文网](http://nodejs.cn)
1010 | - [CNode:Node.js专业中文社区](https://cnodejs.org)
1011 |
1012 | 看视频整理要点笔记:
1013 |
1014 | ---
1015 |
1016 | - [hello-nodejs](#hello-nodejs)
1017 | - [1.课程介绍与开发环境搭建](#1%E8%AF%BE%E7%A8%8B%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA)
1018 | - [2.全局对象](#2%E5%85%A8%E5%B1%80%E5%AF%B9%E8%B1%A1)
1019 |
1020 | ---
1021 |
1022 | ## 1.课程介绍与开发环境搭建
1023 |
1024 | - 主要包括
1025 | - nodejs 基础知识
1026 | - web 服务器
1027 | - 异步 同步 阻塞 非阻塞
1028 |
1029 | - 课程基础
1030 | - javascript 基础
1031 | - html 基础
1032 | - 命令行基础
1033 |
1034 | - Node.js 介绍
1035 | - Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境
1036 | - Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效
1037 | - Node.js 的包管理器 npm,是全球最大的开源库生态系统
1038 | - javascript 是脚本语言,需要解析器才能执行,浏览器就充当了解析器
1039 | - 在Chrome中,解析器就是 V8 引擎,将 javascript 转换成 机器码
1040 | - V8 引擎是开源的,由 C++ 语言编写,性能高
1041 | - Node.js 高性能,事件驱动,非阻塞,生态圈很好
1042 |
1043 | - Node.js 安装
1044 | - [官网](https://nodejs.org/zh-cn/) 下载安装即可,很小不到20M!
1045 | - 验证是否成功,命令行输入 `node -v` 显示版本号如 `v8.11.4`
1046 | - 按提示升级 npm,Update available 5.6.0 → 6.4.1, `npm i -g npm`
1047 | - macOS 安装完提示如下
1048 |
1049 | ```sh
1050 | This package has installed:
1051 | • Node.js v8.11.4 to /usr/local/bin/node
1052 | • npm v5.6.0 to /usr/local/bin/npm
1053 | Make sure that /usr/local/bin is in your $PATH.
1054 | ```
1055 |
1056 | - Node.js 用途
1057 |
1058 | - javascript 运行环境
1059 | - 操作文件(grunt gulp webpack)
1060 | - 操作数据库
1061 | - 写后端 api
1062 | - 命令行工具
1063 | - web 开发
1064 | - 聊天室
1065 |
1066 | - JavaScript 语句后应该加分号么?
1067 | - [知乎讨论](https://www.zhihu.com/question/20298345)
1068 | - 代码风格而已,没有定论
1069 | - 少分号更易读,不累
1070 | - 必须加分号情况很少见:一行开头是括号`(`或者方括号`[`的时候加上分号就可以了,其他时候都不要
1071 | - 如果下一行的行首是`( [ / + -`之一的话,js不会自动在上一行句尾加上分号
1072 |
1073 | ## 2.全局对象
1074 |
1075 | - 全局对象
1076 | - 不用导入,直接使用的对象
1077 | - [官方文档](http://nodejs.cn/api/globals.html#globals_global_objects)
1078 | - Buffer 类,用于处理二进制数据
1079 | - console,用于打印 stdout 和 stderr
1080 | - global, 全局的命名空间对象
1081 | - process,进程对象
1082 | - setTimeout(callback, delay[, ...args])
1083 | - setInterval(callback, delay[, ...args])
1084 | - setImmediate(callback[, ...args])
1085 | - clearTimeout(timeoutObject)
1086 | - clearInterval(intervalObject)
1087 | - clearImmediate(immediateObject)
1088 |
1089 | - 以下变量虽然看起来像全局变量,但实际上不是
1090 | - 全局变量在所有模块中均可使用
1091 | - 以下对象作用域只在模块内,详见 [module文档](http://nodejs.cn/api/modules.html):
1092 | - __dirname
1093 | - __filename
1094 | - exports
1095 | - module
1096 | - require()
1097 |
1098 | - 运行 `.js` 脚本文件
1099 | - `node app` 或者 `node app.js`
1100 |
1101 | - 实践代码
1102 |
1103 | ```js
1104 | console.log('hello world');
1105 |
1106 | setTimeout(function () {
1107 | console.log("3 seconds have passed 2");
1108 | }, 3000);
1109 |
1110 | // 箭头函数,es6的写法
1111 | setTimeout(() => {
1112 | console.log("3 seconds have passed 1");
1113 | }, 3000);
1114 |
1115 | // 每间隔2秒不断执行
1116 | setInterval(function () {
1117 | console.log("2 seconds have passed");
1118 | }, 2000);
1119 |
1120 |
1121 | var time = 0
1122 | var timer = setInterval(function () {
1123 | time += 2;
1124 | console.log(time + " seconds have passed");
1125 | if (time > 6) {
1126 | clearInterval(timer);
1127 | console.log("clearInterval")
1128 | }
1129 | }, 2000)
1130 |
1131 | // 输出当前目录 和 带绝对路径的文件名
1132 | console.log(__dirname)
1133 | console.log(__filename)
1134 |
1135 | console.log('end')
1136 | console.dir(global)
1137 | ```
1138 |
1139 | ## 3.回调函数
1140 |
1141 | ```js
1142 | function sayHi() {
1143 | console.log('Hi')
1144 | }
1145 |
1146 | sayHi() // 调用函数
1147 |
1148 | // 将匿名函数赋给变量
1149 | var sayBye = function (name) {
1150 | console.log(name + ' Bye')
1151 | }
1152 |
1153 | sayBye()
1154 |
1155 | // 第一个参数是函数
1156 | function callFunction(fun, name) {
1157 | fun(name)
1158 | }
1159 |
1160 | callFunction(sayBye, 'able')
1161 | // 或者
1162 | callFunction(function (name) {
1163 | console.log(name + ' Bye')
1164 | }, 'able')
1165 | ```
1166 |
1167 | ## 4.模块
1168 |
1169 | - module 对象
1170 | - 每个文件都被视为独立的模块
1171 | - 每个模块中,module 指向表示当前模块的对象的引用
1172 | - module 实际上不是全局的,而是每个模块本地的
1173 | - module.exports 导出模块内的对象,方便其他对象引用
1174 | - require() 引入模块
1175 | - 当 Node.js 直接运行一个文件时,require.main 会被设为它的 module
1176 | - 可以通过 require.main === module 来判断一个文件是否被直接运行
1177 | - module 提供了一个 filename 属性(通常等同于 __filename)
1178 | - 可以通过检查 require.main.filename 来获取当前应用程序的入口点
1179 |
1180 | ```js
1181 | // counter.js
1182 | var counter = function (arr) {
1183 | return "There are " + arr.length + " elements in array"
1184 | }
1185 |
1186 | var adder = function (a, b) {
1187 | return `the sum of the 2 numbers is ${a+b}`
1188 | }
1189 |
1190 | var pi = 3.14
1191 |
1192 | // 只有一个时可以这样导入
1193 | // module.exports = counter
1194 |
1195 | /*
1196 | module.exports.counter = counter
1197 | module.exports.adder = adder
1198 | module.exports.pi = pi
1199 | */
1200 |
1201 | module.exports = {
1202 | counter: counter,
1203 | adder: adder,
1204 | pi: pi,
1205 | }
1206 | /* 对象可以简写
1207 | module.exports = {
1208 | counter,
1209 | adder,
1210 | pi,
1211 | }
1212 | */
1213 |
1214 | //p4.js
1215 | var stuff = require('./count')
1216 |
1217 | console.log(stuff.counter(['ruby', 'nodejs', 'react']))
1218 | console.log(stuff.adder(3, 2))
1219 | console.log(stuff.pi)
1220 | ```
1221 |
1222 | ## 5.事件 events
1223 |
1224 | - 多数 Node.js 核心 API 都采用异步事件驱动架构
1225 | - 所有能触发事件的对象都是 EventEmitter 类的实例
1226 | - 事件名称通常是驼峰式的字符串
1227 |
1228 | - 实践代码
1229 |
1230 | ```js
1231 | var events = require('events')
1232 | var util = require('util')
1233 |
1234 | // 事件 对象
1235 | var myEmitter = new events.EventEmitter()
1236 |
1237 | // 绑定 事件名称 和 回调函数
1238 | myEmitter.on('someEvent', function (message) {
1239 | console.log(message)
1240 | })
1241 |
1242 | // 触发实践,使用事件名称
1243 | myEmitter.emit('someEvent', 'The event was emitted')
1244 |
1245 | // 创建对象
1246 | var Person = function (name) {
1247 | this.name = name
1248 | }
1249 |
1250 | // 继承,让Person类具有事件对象的特性,绑定和触发事件
1251 | util.inherits(Person, events.EventEmitter)
1252 | // 新建对象
1253 | var xiaoming = new Person('xiaoming')
1254 | var lili = new Person('lili')
1255 |
1256 | var person = [xiaoming, lili]
1257 |
1258 | // 循环person数组,绑定事件
1259 | person.forEach(function (person) {
1260 | person.on('speak', function (message) {
1261 | console.log(person.name + ' said: ' + message)
1262 | })
1263 | })
1264 |
1265 | // 触发事件
1266 | xiaoming.emit('speak', 'hi')
1267 | lili.emit('speak', 'I want a curry')
1268 | ```
1269 |
1270 | ## 6.读写文件(同步和异步)
1271 |
1272 | ```js
1273 | var fs = require('fs')
1274 |
1275 | // 同步读写文件,顺序执行,如果读取时间很长,会阻塞进程
1276 | var readMe = fs.readFileSync('readMe.txt', 'utf8')
1277 | fs.writeFileSync('writeMe.txt', readMe)
1278 |
1279 | console.log(readMe)
1280 | console.log('finished sync')
1281 |
1282 | // 异步读写文件
1283 | // 异步事件,Nodejs 维护一个事件队列,注册事件,完成后执行主线程
1284 | // 当主线程空闲时,取出执行事件,从线程池中发起线程执行事件, 当事件执行完成后通知主线程。这就是异步高效的原因。
1285 |
1286 | var readMe = fs.readFile('readMe.txt', 'utf8', function (err, data) {
1287 | fs.writeFile('writeMe.txt', data, function () {
1288 | console.log('writeMe has finished')
1289 | })
1290 | })
1291 |
1292 | console.log('end')
1293 | ```
1294 |
1295 | ## 7.创建和删除目录
1296 |
1297 | - [ fs - 文件系统 API 文档](http://nodejs.cn/api/fs.html#fs_fs_unlink_path_callback)
1298 |
1299 | ```js
1300 | var fs = require('fs')
1301 |
1302 | // 异步删除文件
1303 | fs.unlink('writeMe.txt', function () {
1304 | console.log('delete writeMe.txt file')
1305 | })
1306 |
1307 | // 同步创建和删除目录
1308 | fs.mkdirSync('stuff')
1309 | fs.rmdirSync('stuff')
1310 |
1311 | // 异步
1312 | fs.mkdir('stuff', function () {
1313 | fs.readFile('readMe.txt', 'utf8', function (err, data) {
1314 | fs.writeFile('./stuff/writeMe.txt', data, function () {
1315 | console.log('copy successfully')
1316 | })
1317 | })
1318 | })
1319 | ```
1320 |
1321 | ## 8.流和管道
1322 |
1323 | - 流(stream)
1324 | - 处理流式数据的抽象接口
1325 | - stream 模块提供了一些基础的 API,用于构建实现了流接口的对象
1326 | - 流可以是可读的、可写的、或是可读写的,所有的流都是 EventEmitter 的实例
1327 | - 流处理数据通过缓存可以提高性能
1328 | # hello-nodejs
1329 |
1330 | 轻松学 Node.js 基础篇 入门
1331 |
1332 | 视频地址
1333 |
1334 | - [https://www.rails365.net](https://www.rails365.net/movies/qing-song-xue-nodejs-ji-chu-pian-1-ke-cheng-jie-shao-yu-kai-fa-huan-jing-da-jian)
1335 | - [b站](https://www.bilibili.com/video/av21010015)
1336 |
1337 | 常用链接
1338 |
1339 | - [Node.js 官网](https://nodejs.org/zh-cn/)
1340 | - [Node.js 中文网](http://nodejs.cn)
1341 | - [CNode:Node.js专业中文社区](https://cnodejs.org)
1342 |
1343 | 看视频整理要点笔记:
1344 |
1345 | ---
1346 |
1347 | - [hello-nodejs](#hello-nodejs)
1348 | - [1.课程介绍与开发环境搭建](#1%E8%AF%BE%E7%A8%8B%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA)
1349 | - [2.全局对象](#2%E5%85%A8%E5%B1%80%E5%AF%B9%E8%B1%A1)
1350 |
1351 | ---
1352 |
1353 | ## 1.课程介绍与开发环境搭建
1354 |
1355 | - 主要包括
1356 | - nodejs 基础知识
1357 | - web 服务器
1358 | - 异步 同步 阻塞 非阻塞
1359 |
1360 | - 课程基础
1361 | - javascript 基础
1362 | - html 基础
1363 | - 命令行基础
1364 |
1365 | - Node.js 介绍
1366 | - Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境
1367 | - Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效
1368 | - Node.js 的包管理器 npm,是全球最大的开源库生态系统
1369 | - javascript 是脚本语言,需要解析器才能执行,浏览器就充当了解析器
1370 | - 在Chrome中,解析器就是 V8 引擎,将 javascript 转换成 机器码
1371 | - V8 引擎是开源的,由 C++ 语言编写,性能高
1372 | - Node.js 高性能,事件驱动,非阻塞,生态圈很好
1373 |
1374 | - Node.js 安装
1375 | - [官网](https://nodejs.org/zh-cn/) 下载安装即可,很小不到20M!
1376 | - 验证是否成功,命令行输入 `node -v` 显示版本号如 `v8.11.4`
1377 | - 按提示升级 npm,Update available 5.6.0 → 6.4.1, `npm i -g npm`
1378 | - macOS 安装完提示如下
1379 |
1380 | ```sh
1381 | This package has installed:
1382 | • Node.js v8.11.4 to /usr/local/bin/node
1383 | • npm v5.6.0 to /usr/local/bin/npm
1384 | Make sure that /usr/local/bin is in your $PATH.
1385 | ```
1386 |
1387 | - Node.js 用途
1388 |
1389 | - javascript 运行环境
1390 | - 操作文件(grunt gulp webpack)
1391 | - 操作数据库
1392 | - 写后端 api
1393 | - 命令行工具
1394 | - web 开发
1395 | - 聊天室
1396 |
1397 | - JavaScript 语句后应该加分号么?
1398 | - [知乎讨论](https://www.zhihu.com/question/20298345)
1399 | - 代码风格而已,没有定论
1400 | - 少分号更易读,不累
1401 | - 必须加分号情况很少见:一行开头是括号`(`或者方括号`[`的时候加上分号就可以了,其他时候都不要
1402 | - 如果下一行的行首是`( [ / + -`之一的话,js不会自动在上一行句尾加上分号
1403 |
1404 | ## 2.全局对象
1405 |
1406 | - 全局对象
1407 | - 不用导入,直接使用的对象
1408 | - [官方文档](http://nodejs.cn/api/globals.html#globals_global_objects)
1409 | - Buffer 类,用于处理二进制数据
1410 | - console,用于打印 stdout 和 stderr
1411 | - global, 全局的命名空间对象
1412 | - process,进程对象
1413 | - setTimeout(callback, delay[, ...args])
1414 | - setInterval(callback, delay[, ...args])
1415 | - setImmediate(callback[, ...args])
1416 | - clearTimeout(timeoutObject)
1417 | - clearInterval(intervalObject)
1418 | - clearImmediate(immediateObject)
1419 |
1420 | - 以下变量虽然看起来像全局变量,但实际上不是
1421 | - 全局变量在所有模块中均可使用
1422 | - 以下对象作用域只在模块内,详见 [module文档](http://nodejs.cn/api/modules.html):
1423 | - __dirname
1424 | - __filename
1425 | - exports
1426 | - module
1427 | - require()
1428 |
1429 | - 运行 `.js` 脚本文件
1430 | - `node app` 或者 `node app.js`
1431 |
1432 | - 实践代码
1433 |
1434 | ```js
1435 | console.log('hello world');
1436 |
1437 | setTimeout(function () {
1438 | console.log("3 seconds have passed 2");
1439 | }, 3000);
1440 |
1441 | // 箭头函数,es6的写法
1442 | setTimeout(() => {
1443 | console.log("3 seconds have passed 1");
1444 | }, 3000);
1445 |
1446 | // 每间隔2秒不断执行
1447 | setInterval(function () {
1448 | console.log("2 seconds have passed");
1449 | }, 2000);
1450 |
1451 |
1452 | var time = 0
1453 | var timer = setInterval(function () {
1454 | time += 2;
1455 | console.log(time + " seconds have passed");
1456 | if (time > 6) {
1457 | clearInterval(timer);
1458 | console.log("clearInterval")
1459 | }
1460 | }, 2000)
1461 |
1462 | // 输出当前目录 和 带绝对路径的文件名
1463 | console.log(__dirname)
1464 | console.log(__filename)
1465 |
1466 | console.log('end')
1467 | console.dir(global)
1468 | ```
1469 |
1470 | ## 3.回调函数
1471 |
1472 | ```js
1473 | function sayHi() {
1474 | console.log('Hi')
1475 | }
1476 |
1477 | sayHi() // 调用函数
1478 |
1479 | // 将匿名函数赋给变量
1480 | var sayBye = function (name) {
1481 | console.log(name + ' Bye')
1482 | }
1483 |
1484 | sayBye()
1485 |
1486 | // 第一个参数是函数
1487 | function callFunction(fun, name) {
1488 | fun(name)
1489 | }
1490 |
1491 | callFunction(sayBye, 'able')
1492 | // 或者
1493 | callFunction(function (name) {
1494 | console.log(name + ' Bye')
1495 | }, 'able')
1496 | ```
1497 |
1498 | ## 4.模块
1499 |
1500 | - module 对象
1501 | - 每个文件都被视为独立的模块
1502 | - 每个模块中,module 指向表示当前模块的对象的引用
1503 | - module 实际上不是全局的,而是每个模块本地的
1504 | - module.exports 导出模块内的对象,方便其他对象引用
1505 | - require() 引入模块
1506 | - 当 Node.js 直接运行一个文件时,require.main 会被设为它的 module
1507 | - 可以通过 require.main === module 来判断一个文件是否被直接运行
1508 | - module 提供了一个 filename 属性(通常等同于 __filename)
1509 | - 可以通过检查 require.main.filename 来获取当前应用程序的入口点
1510 |
1511 | ```js
1512 | // counter.js
1513 | var counter = function (arr) {
1514 | return "There are " + arr.length + " elements in array"
1515 | }
1516 |
1517 | var adder = function (a, b) {
1518 | return `the sum of the 2 numbers is ${a+b}`
1519 | }
1520 |
1521 | var pi = 3.14
1522 |
1523 | // 只有一个时可以这样导入
1524 | // module.exports = counter
1525 |
1526 | /*
1527 | module.exports.counter = counter
1528 | module.exports.adder = adder
1529 | module.exports.pi = pi
1530 | */
1531 |
1532 | module.exports = {
1533 | counter: counter,
1534 | adder: adder,
1535 | pi: pi,
1536 | }
1537 | /* 对象可以简写
1538 | module.exports = {
1539 | counter,
1540 | adder,
1541 | pi,
1542 | }
1543 | */
1544 |
1545 | //p4.js
1546 | var stuff = require('./count')
1547 |
1548 | console.log(stuff.counter(['ruby', 'nodejs', 'react']))
1549 | console.log(stuff.adder(3, 2))
1550 | console.log(stuff.pi)
1551 | ```
1552 |
1553 | ## 5.事件 events
1554 |
1555 | - 多数 Node.js 核心 API 都采用异步事件驱动架构
1556 | - 所有能触发事件的对象都是 EventEmitter 类的实例
1557 | - 事件名称通常是驼峰式的字符串
1558 |
1559 | - 实践代码
1560 |
1561 | ```js
1562 | var events = require('events')
1563 | var util = require('util')
1564 |
1565 | // 事件 对象
1566 | var myEmitter = new events.EventEmitter()
1567 |
1568 | // 绑定 事件名称 和 回调函数
1569 | myEmitter.on('someEvent', function (message) {
1570 | console.log(message)
1571 | })
1572 |
1573 | // 触发实践,使用事件名称
1574 | myEmitter.emit('someEvent', 'The event was emitted')
1575 |
1576 | // 创建对象
1577 | var Person = function (name) {
1578 | this.name = name
1579 | }
1580 |
1581 | // 继承,让Person类具有事件对象的特性,绑定和触发事件
1582 | util.inherits(Person, events.EventEmitter)
1583 | // 新建对象
1584 | var xiaoming = new Person('xiaoming')
1585 | var lili = new Person('lili')
1586 |
1587 | var person = [xiaoming, lili]
1588 |
1589 | // 循环person数组,绑定事件
1590 | person.forEach(function (person) {
1591 | person.on('speak', function (message) {
1592 | console.log(person.name + ' said: ' + message)
1593 | })
1594 | })
1595 |
1596 | // 触发事件
1597 | xiaoming.emit('speak', 'hi')
1598 | lili.emit('speak', 'I want a curry')
1599 | ```
1600 |
1601 | ## 6.读写文件(同步和异步)
1602 |
1603 | ```js
1604 | var fs = require('fs')
1605 |
1606 | // 同步读写文件,顺序执行,如果读取时间很长,会阻塞进程
1607 | var readMe = fs.readFileSync('readMe.txt', 'utf8')
1608 | fs.writeFileSync('writeMe.txt', readMe)
1609 |
1610 | console.log(readMe)
1611 | console.log('finished sync')
1612 |
1613 | // 异步读写文件
1614 | // 异步事件,Nodejs 维护一个事件队列,注册事件,完成后执行主线程
1615 | // 当主线程空闲时,取出执行事件,从线程池中发起线程执行事件, 当事件执行完成后通知主线程。这就是异步高效的原因。
1616 |
1617 | var readMe = fs.readFile('readMe.txt', 'utf8', function (err, data) {
1618 | fs.writeFile('writeMe.txt', data, function () {
1619 | console.log('writeMe has finished')
1620 | })
1621 | })
1622 |
1623 | console.log('end')
1624 | ```
1625 |
1626 | ## 7.创建和删除目录
1627 |
1628 | - [ fs - 文件系统 API 文档](http://nodejs.cn/api/fs.html#fs_fs_unlink_path_callback)
1629 |
1630 | ```js
1631 | var fs = require('fs')
1632 |
1633 | // 异步删除文件
1634 | fs.unlink('writeMe.txt', function () {
1635 | console.log('delete writeMe.txt file')
1636 | })
1637 |
1638 | // 同步创建和删除目录
1639 | fs.mkdirSync('stuff')
1640 | fs.rmdirSync('stuff')
1641 |
1642 | // 异步
1643 | fs.mkdir('stuff', function () {
1644 | fs.readFile('readMe.txt', 'utf8', function (err, data) {
1645 | fs.writeFile('./stuff/writeMe.txt', data, function () {
1646 | console.log('copy successfully')
1647 | })
1648 | })
1649 | })
1650 | ```
1651 |
1652 | ## 8.流和管道
1653 |
1654 | - 流(stream)
1655 | - 处理流式数据的抽象接口
1656 | - stream 模块提供了一些基础的 API,用于构建实现了流接口的对象
1657 | - 流可以是可读的、可写的、或是可读写的,所有的流都是 EventEmitter 的实例
1658 | - 流处理数据通过缓存可以提高性能
1659 |
1660 |
--------------------------------------------------------------------------------
/review.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 | review page
11 |
12 |
--------------------------------------------------------------------------------
/router.js:
--------------------------------------------------------------------------------
1 | fs = require('fs')
2 |
3 | function route(handle, pathname, res, params) {
4 | console.log('Routing a request for ' + pathname)
5 | if (typeof handle[pathname] === 'function') {
6 | handle[pathname](res, params)
7 | } else {
8 | console.log('No handle for ' + pathname)
9 | res.writeHead(200, { 'Content-Type': 'text/html' })
10 | fs.createReadStream(__dirname + '/404.html', 'utf8').pipe(res)
11 | }
12 | }
13 |
14 | module.exports.route = route
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | var http = require('http')
2 | var url = require('url')
3 | var querystring = require('querystring')
4 |
5 | function startServer(route, handle) {
6 | var onRequest = function (req, res) {
7 | console.log('request received ' + req.url)
8 | var pathname = url.parse(req.url).pathname
9 |
10 | var data = ""
11 | req.on("error", function (err) {
12 | console.error(err)
13 | }).on("data", function (chunk) {
14 | data += chunk
15 | }).on("end", function () {
16 | if (req.mothod === "POST") {
17 | if (data.length > 1e6) {
18 | req.connection.destroy() // 如果数据很大,就断开
19 | }
20 | route(handle, pathname, res, querystring.parse(data))
21 | } else {
22 | var params = url.parse(req.url, true).query
23 | route(handle, pathname, res, params)
24 | }
25 | })
26 | // 或者
27 | // var data = []
28 | // data.push(chunk)
29 | // data = Buffer.concat(data).toString()
30 |
31 | }
32 | var server = http.createServer(onRequest)
33 | server.listen(3000)
34 | console.log('server started on http://127.0.0.1:3000')
35 | }
36 |
37 | module.exports.startServer = startServer
--------------------------------------------------------------------------------
/stuff/writeMe.txt:
--------------------------------------------------------------------------------
1 | you read me!
2 |
--------------------------------------------------------------------------------
/writeMe.txt:
--------------------------------------------------------------------------------
1 | you read me!
2 |
3 | # hello-nodejs
4 |
5 | 轻松学 Node.js 基础篇 入门
6 |
7 | 视频地址
8 |
9 | - [https://www.rails365.net](https://www.rails365.net/movies/qing-song-xue-nodejs-ji-chu-pian-1-ke-cheng-jie-shao-yu-kai-fa-huan-jing-da-jian)
10 | - [b站](https://www.bilibili.com/video/av21010015)
11 |
12 | 常用链接
13 |
14 | - [Node.js 官网](https://nodejs.org/zh-cn/)
15 | - [Node.js 中文网](http://nodejs.cn)
16 | - [CNode:Node.js专业中文社区](https://cnodejs.org)
17 |
18 | 看视频整理要点笔记:
19 |
20 | ---
21 |
22 | - [hello-nodejs](#hello-nodejs)
23 | - [1.课程介绍与开发环境搭建](#1%E8%AF%BE%E7%A8%8B%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA)
24 | - [2.全局对象](#2%E5%85%A8%E5%B1%80%E5%AF%B9%E8%B1%A1)
25 |
26 | ---
27 |
28 | ## 1.课程介绍与开发环境搭建
29 |
30 | - 主要包括
31 | - nodejs 基础知识
32 | - web 服务器
33 | - 异步 同步 阻塞 非阻塞
34 |
35 | - 课程基础
36 | - javascript 基础
37 | - html 基础
38 | - 命令行基础
39 |
40 | - Node.js 介绍
41 | - Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境
42 | - Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效
43 | - Node.js 的包管理器 npm,是全球最大的开源库生态系统
44 | - javascript 是脚本语言,需要解析器才能执行,浏览器就充当了解析器
45 | - 在Chrome中,解析器就是 V8 引擎,将 javascript 转换成 机器码
46 | - V8 引擎是开源的,由 C++ 语言编写,性能高
47 | - Node.js 高性能,事件驱动,非阻塞,生态圈很好
48 |
49 | - Node.js 安装
50 | - [官网](https://nodejs.org/zh-cn/) 下载安装即可,很小不到20M!
51 | - 验证是否成功,命令行输入 `node -v` 显示版本号如 `v8.11.4`
52 | - 按提示升级 npm,Update available 5.6.0 → 6.4.1, `npm i -g npm`
53 | - macOS 安装完提示如下
54 |
55 | ```sh
56 | This package has installed:
57 | • Node.js v8.11.4 to /usr/local/bin/node
58 | • npm v5.6.0 to /usr/local/bin/npm
59 | Make sure that /usr/local/bin is in your $PATH.
60 | ```
61 |
62 | - Node.js 用途
63 |
64 | - javascript 运行环境
65 | - 操作文件(grunt gulp webpack)
66 | - 操作数据库
67 | - 写后端 api
68 | - 命令行工具
69 | - web 开发
70 | - 聊天室
71 |
72 | - JavaScript 语句后应该加分号么?
73 | - [知乎讨论](https://www.zhihu.com/question/20298345)
74 | - 代码风格而已,没有定论
75 | - 少分号更易读,不累
76 | - 必须加分号情况很少见:一行开头是括号`(`或者方括号`[`的时候加上分号就可以了,其他时候都不要
77 | - 如果下一行的行首是`( [ / + -`之一的话,js不会自动在上一行句尾加上分号
78 |
79 | ## 2.全局对象
80 |
81 | - 全局对象
82 | - 不用导入,直接使用的对象
83 | - [官方文档](http://nodejs.cn/api/globals.html#globals_global_objects)
84 | - Buffer 类,用于处理二进制数据
85 | - console,用于打印 stdout 和 stderr
86 | - global, 全局的命名空间对象
87 | - process,进程对象
88 | - setTimeout(callback, delay[, ...args])
89 | - setInterval(callback, delay[, ...args])
90 | - setImmediate(callback[, ...args])
91 | - clearTimeout(timeoutObject)
92 | - clearInterval(intervalObject)
93 | - clearImmediate(immediateObject)
94 |
95 | - 以下变量虽然看起来像全局变量,但实际上不是
96 | - 全局变量在所有模块中均可使用
97 | - 以下对象作用域只在模块内,详见 [module文档](http://nodejs.cn/api/modules.html):
98 | - __dirname
99 | - __filename
100 | - exports
101 | - module
102 | - require()
103 |
104 | - 运行 `.js` 脚本文件
105 | - `node app` 或者 `node app.js`
106 |
107 | - 实践代码
108 |
109 | ```js
110 | console.log('hello world');
111 |
112 | setTimeout(function () {
113 | console.log("3 seconds have passed 2");
114 | }, 3000);
115 |
116 | // 箭头函数,es6的写法
117 | setTimeout(() => {
118 | console.log("3 seconds have passed 1");
119 | }, 3000);
120 |
121 | // 每间隔2秒不断执行
122 | setInterval(function () {
123 | console.log("2 seconds have passed");
124 | }, 2000);
125 |
126 |
127 | var time = 0
128 | var timer = setInterval(function () {
129 | time += 2;
130 | console.log(time + " seconds have passed");
131 | if (time > 6) {
132 | clearInterval(timer);
133 | console.log("clearInterval")
134 | }
135 | }, 2000)
136 |
137 | // 输出当前目录 和 带绝对路径的文件名
138 | console.log(__dirname)
139 | console.log(__filename)
140 |
141 | console.log('end')
142 | console.dir(global)
143 | ```
144 |
145 | ## 3.回调函数
146 |
147 | ```js
148 | function sayHi() {
149 | console.log('Hi')
150 | }
151 |
152 | sayHi() // 调用函数
153 |
154 | // 将匿名函数赋给变量
155 | var sayBye = function (name) {
156 | console.log(name + ' Bye')
157 | }
158 |
159 | sayBye()
160 |
161 | // 第一个参数是函数
162 | function callFunction(fun, name) {
163 | fun(name)
164 | }
165 |
166 | callFunction(sayBye, 'able')
167 | // 或者
168 | callFunction(function (name) {
169 | console.log(name + ' Bye')
170 | }, 'able')
171 | ```
172 |
173 | ## 4.模块
174 |
175 | - module 对象
176 | - 每个文件都被视为独立的模块
177 | - 每个模块中,module 指向表示当前模块的对象的引用
178 | - module 实际上不是全局的,而是每个模块本地的
179 | - module.exports 导出模块内的对象,方便其他对象引用
180 | - require() 引入模块
181 | - 当 Node.js 直接运行一个文件时,require.main 会被设为它的 module
182 | - 可以通过 require.main === module 来判断一个文件是否被直接运行
183 | - module 提供了一个 filename 属性(通常等同于 __filename)
184 | - 可以通过检查 require.main.filename 来获取当前应用程序的入口点
185 |
186 | ```js
187 | // counter.js
188 | var counter = function (arr) {
189 | return "There are " + arr.length + " elements in array"
190 | }
191 |
192 | var adder = function (a, b) {
193 | return `the sum of the 2 numbers is ${a+b}`
194 | }
195 |
196 | var pi = 3.14
197 |
198 | // 只有一个时可以这样导入
199 | // module.exports = counter
200 |
201 | /*
202 | module.exports.counter = counter
203 | module.exports.adder = adder
204 | module.exports.pi = pi
205 | */
206 |
207 | module.exports = {
208 | counter: counter,
209 | adder: adder,
210 | pi: pi,
211 | }
212 | /* 对象可以简写
213 | module.exports = {
214 | counter,
215 | adder,
216 | pi,
217 | }
218 | */
219 |
220 | //p4.js
221 | var stuff = require('./count')
222 |
223 | console.log(stuff.counter(['ruby', 'nodejs', 'react']))
224 | console.log(stuff.adder(3, 2))
225 | console.log(stuff.pi)
226 | ```
227 |
228 | ## 5.事件 events
229 |
230 | - 多数 Node.js 核心 API 都采用异步事件驱动架构
231 | - 所有能触发事件的对象都是 EventEmitter 类的实例
232 | - 事件名称通常是驼峰式的字符串
233 |
234 | - 实践代码
235 |
236 | ```js
237 | var events = require('events')
238 | var util = require('util')
239 |
240 | // 事件 对象
241 | var myEmitter = new events.EventEmitter()
242 |
243 | // 绑定 事件名称 和 回调函数
244 | myEmitter.on('someEvent', function (message) {
245 | console.log(message)
246 | })
247 |
248 | // 触发实践,使用事件名称
249 | myEmitter.emit('someEvent', 'The event was emitted')
250 |
251 | // 创建对象
252 | var Person = function (name) {
253 | this.name = name
254 | }
255 |
256 | // 继承,让Person类具有事件对象的特性,绑定和触发事件
257 | util.inherits(Person, events.EventEmitter)
258 | // 新建对象
259 | var xiaoming = new Person('xiaoming')
260 | var lili = new Person('lili')
261 |
262 | var person = [xiaoming, lili]
263 |
264 | // 循环person数组,绑定事件
265 | person.forEach(function (person) {
266 | person.on('speak', function (message) {
267 | console.log(person.name + ' said: ' + message)
268 | })
269 | })
270 |
271 | // 触发事件
272 | xiaoming.emit('speak', 'hi')
273 | lili.emit('speak', 'I want a curry')
274 | ```
275 |
276 | ## 6.读写文件(同步和异步)
277 |
278 | ```js
279 | var fs = require('fs')
280 |
281 | // 同步读写文件,顺序执行,如果读取时间很长,会阻塞进程
282 | var readMe = fs.readFileSync('readMe.txt', 'utf8')
283 | fs.writeFileSync('writeMe.txt', readMe)
284 |
285 | console.log(readMe)
286 | console.log('finished sync')
287 |
288 | // 异步读写文件
289 | // 异步事件,Nodejs 维护一个事件队列,注册事件,完成后执行主线程
290 | // 当主线程空闲时,取出执行事件,从线程池中发起线程执行事件, 当事件执行完成后通知主线程。这就是异步高效的原因。
291 |
292 | var readMe = fs.readFile('readMe.txt', 'utf8', function (err, data) {
293 | fs.writeFile('writeMe.txt', data, function () {
294 | console.log('writeMe has finished')
295 | })
296 | })
297 |
298 | console.log('end')
299 | ```
300 |
301 | ## 7.创建和删除目录
302 |
303 | - [ fs - 文件系统 API 文档](http://nodejs.cn/api/fs.html#fs_fs_unlink_path_callback)
304 |
305 | ```js
306 | var fs = require('fs')
307 |
308 | // 异步删除文件
309 | fs.unlink('writeMe.txt', function () {
310 | console.log('delete writeMe.txt file')
311 | })
312 |
313 | // 同步创建和删除目录
314 | fs.mkdirSync('stuff')
315 | fs.rmdirSync('stuff')
316 |
317 | // 异步
318 | fs.mkdir('stuff', function () {
319 | fs.readFile('readMe.txt', 'utf8', function (err, data) {
320 | fs.writeFile('./stuff/writeMe.txt', data, function () {
321 | console.log('copy successfully')
322 | })
323 | })
324 | })
325 | ```
326 |
327 | ## 8.流和管道
328 |
329 | - 流(stream)
330 | - 处理流式数据的抽象接口
331 | - stream 模块提供了一些基础的 API,用于构建实现了流接口的对象
332 | - 流可以是可读的、可写的、或是可读写的,所有的流都是 EventEmitter 的实例
333 | - 流处理数据通过缓存可以提高性能
334 |
335 | # hello-nodejs
336 |
337 | 轻松学 Node.js 基础篇 入门
338 |
339 | 视频地址
340 |
341 | - [https://www.rails365.net](https://www.rails365.net/movies/qing-song-xue-nodejs-ji-chu-pian-1-ke-cheng-jie-shao-yu-kai-fa-huan-jing-da-jian)
342 | - [b站](https://www.bilibili.com/video/av21010015)
343 |
344 | 常用链接
345 |
346 | - [Node.js 官网](https://nodejs.org/zh-cn/)
347 | - [Node.js 中文网](http://nodejs.cn)
348 | - [CNode:Node.js专业中文社区](https://cnodejs.org)
349 |
350 | 看视频整理要点笔记:
351 |
352 | ---
353 |
354 | - [hello-nodejs](#hello-nodejs)
355 | - [1.课程介绍与开发环境搭建](#1%E8%AF%BE%E7%A8%8B%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA)
356 | - [2.全局对象](#2%E5%85%A8%E5%B1%80%E5%AF%B9%E8%B1%A1)
357 |
358 | ---
359 |
360 | ## 1.课程介绍与开发环境搭建
361 |
362 | - 主要包括
363 | - nodejs 基础知识
364 | - web 服务器
365 | - 异步 同步 阻塞 非阻塞
366 |
367 | - 课程基础
368 | - javascript 基础
369 | - html 基础
370 | - 命令行基础
371 |
372 | - Node.js 介绍
373 | - Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境
374 | - Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效
375 | - Node.js 的包管理器 npm,是全球最大的开源库生态系统
376 | - javascript 是脚本语言,需要解析器才能执行,浏览器就充当了解析器
377 | - 在Chrome中,解析器就是 V8 引擎,将 javascript 转换成 机器码
378 | - V8 引擎是开源的,由 C++ 语言编写,性能高
379 | - Node.js 高性能,事件驱动,非阻塞,生态圈很好
380 |
381 | - Node.js 安装
382 | - [官网](https://nodejs.org/zh-cn/) 下载安装即可,很小不到20M!
383 | - 验证是否成功,命令行输入 `node -v` 显示版本号如 `v8.11.4`
384 | - 按提示升级 npm,Update available 5.6.0 → 6.4.1, `npm i -g npm`
385 | - macOS 安装完提示如下
386 |
387 | ```sh
388 | This package has installed:
389 | • Node.js v8.11.4 to /usr/local/bin/node
390 | • npm v5.6.0 to /usr/local/bin/npm
391 | Make sure that /usr/local/bin is in your $PATH.
392 | ```
393 |
394 | - Node.js 用途
395 |
396 | - javascript 运行环境
397 | - 操作文件(grunt gulp webpack)
398 | - 操作数据库
399 | - 写后端 api
400 | - 命令行工具
401 | - web 开发
402 | - 聊天室
403 |
404 | - JavaScript 语句后应该加分号么?
405 | - [知乎讨论](https://www.zhihu.com/question/20298345)
406 | - 代码风格而已,没有定论
407 | - 少分号更易读,不累
408 | - 必须加分号情况很少见:一行开头是括号`(`或者方括号`[`的时候加上分号就可以了,其他时候都不要
409 | - 如果下一行的行首是`( [ / + -`之一的话,js不会自动在上一行句尾加上分号
410 |
411 | ## 2.全局对象
412 |
413 | - 全局对象
414 | - 不用导入,直接使用的对象
415 | - [官方文档](http://nodejs.cn/api/globals.html#globals_global_objects)
416 | - Buffer 类,用于处理二进制数据
417 | - console,用于打印 stdout 和 stderr
418 | - global, 全局的命名空间对象
419 | - process,进程对象
420 | - setTimeout(callback, delay[, ...args])
421 | - setInterval(callback, delay[, ...args])
422 | - setImmediate(callback[, ...args])
423 | - clearTimeout(timeoutObject)
424 | - clearInterval(intervalObject)
425 | - clearImmediate(immediateObject)
426 |
427 | - 以下变量虽然看起来像全局变量,但实际上不是
428 | - 全局变量在所有模块中均可使用
429 | - 以下对象作用域只在模块内,详见 [module文档](http://nodejs.cn/api/modules.html):
430 | - __dirname
431 | - __filename
432 | - exports
433 | - module
434 | - require()
435 |
436 | - 运行 `.js` 脚本文件
437 | - `node app` 或者 `node app.js`
438 |
439 | - 实践代码
440 |
441 | ```js
442 | console.log('hello world');
443 |
444 | setTimeout(function () {
445 | console.log("3 seconds have passed 2");
446 | }, 3000);
447 |
448 | // 箭头函数,es6的写法
449 | setTimeout(() => {
450 | console.log("3 seconds have passed 1");
451 | }, 3000);
452 |
453 | // 每间隔2秒不断执行
454 | setInterval(function () {
455 | console.log("2 seconds have passed");
456 | }, 2000);
457 |
458 |
459 | var time = 0
460 | var timer = setInterval(function () {
461 | time += 2;
462 | console.log(time + " seconds have passed");
463 | if (time > 6) {
464 | clearInterval(timer);
465 | console.log("clearInterval")
466 | }
467 | }, 2000)
468 |
469 | // 输出当前目录 和 带绝对路径的文件名
470 | console.log(__dirname)
471 | console.log(__filename)
472 |
473 | console.log('end')
474 | console.dir(global)
475 | ```
476 |
477 | ## 3.回调函数
478 |
479 | ```js
480 | function sayHi() {
481 | console.log('Hi')
482 | }
483 |
484 | sayHi() // 调用函数
485 |
486 | // 将匿名函数赋给变量
487 | var sayBye = function (name) {
488 | console.log(name + ' Bye')
489 | }
490 |
491 | sayBye()
492 |
493 | // 第一个参数是函数
494 | function callFunction(fun, name) {
495 | fun(name)
496 | }
497 |
498 | callFunction(sayBye, 'able')
499 | // 或者
500 | callFunction(function (name) {
501 | console.log(name + ' Bye')
502 | }, 'able')
503 | ```
504 |
505 | ## 4.模块
506 |
507 | - module 对象
508 | - 每个文件都被视为独立的模块
509 | - 每个模块中,module 指向表示当前模块的对象的引用
510 | - module 实际上不是全局的,而是每个模块本地的
511 | - module.exports 导出模块内的对象,方便其他对象引用
512 | - require() 引入模块
513 | - 当 Node.js 直接运行一个文件时,require.main 会被设为它的 module
514 | - 可以通过 require.main === module 来判断一个文件是否被直接运行
515 | - module 提供了一个 filename 属性(通常等同于 __filename)
516 | - 可以通过检查 require.main.filename 来获取当前应用程序的入口点
517 |
518 | ```js
519 | // counter.js
520 | var counter = function (arr) {
521 | return "There are " + arr.length + " elements in array"
522 | }
523 |
524 | var adder = function (a, b) {
525 | return `the sum of the 2 numbers is ${a+b}`
526 | }
527 |
528 | var pi = 3.14
529 |
530 | // 只有一个时可以这样导入
531 | // module.exports = counter
532 |
533 | /*
534 | module.exports.counter = counter
535 | module.exports.adder = adder
536 | module.exports.pi = pi
537 | */
538 |
539 | module.exports = {
540 | counter: counter,
541 | adder: adder,
542 | pi: pi,
543 | }
544 | /* 对象可以简写
545 | module.exports = {
546 | counter,
547 | adder,
548 | pi,
549 | }
550 | */
551 |
552 | //p4.js
553 | var stuff = require('./count')
554 |
555 | console.log(stuff.counter(['ruby', 'nodejs', 'react']))
556 | console.log(stuff.adder(3, 2))
557 | console.log(stuff.pi)
558 | ```
559 |
560 | ## 5.事件 events
561 |
562 | - 多数 Node.js 核心 API 都采用异步事件驱动架构
563 | - 所有能触发事件的对象都是 EventEmitter 类的实例
564 | - 事件名称通常是驼峰式的字符串
565 |
566 | - 实践代码
567 |
568 | ```js
569 | var events = require('events')
570 | var util = require('util')
571 |
572 | // 事件 对象
573 | var myEmitter = new events.EventEmitter()
574 |
575 | // 绑定 事件名称 和 回调函数
576 | myEmitter.on('someEvent', function (message) {
577 | console.log(message)
578 | })
579 |
580 | // 触发实践,使用事件名称
581 | myEmitter.emit('someEvent', 'The event was emitted')
582 |
583 | // 创建对象
584 | var Person = function (name) {
585 | this.name = name
586 | }
587 |
588 | // 继承,让Person类具有事件对象的特性,绑定和触发事件
589 | util.inherits(Person, events.EventEmitter)
590 | // 新建对象
591 | var xiaoming = new Person('xiaoming')
592 | var lili = new Person('lili')
593 |
594 | var person = [xiaoming, lili]
595 |
596 | // 循环person数组,绑定事件
597 | person.forEach(function (person) {
598 | person.on('speak', function (message) {
599 | console.log(person.name + ' said: ' + message)
600 | })
601 | })
602 |
603 | // 触发事件
604 | xiaoming.emit('speak', 'hi')
605 | lili.emit('speak', 'I want a curry')
606 | ```
607 |
608 | ## 6.读写文件(同步和异步)
609 |
610 | ```js
611 | var fs = require('fs')
612 |
613 | // 同步读写文件,顺序执行,如果读取时间很长,会阻塞进程
614 | var readMe = fs.readFileSync('readMe.txt', 'utf8')
615 | fs.writeFileSync('writeMe.txt', readMe)
616 |
617 | console.log(readMe)
618 | console.log('finished sync')
619 |
620 | // 异步读写文件
621 | // 异步事件,Nodejs 维护一个事件队列,注册事件,完成后执行主线程
622 | // 当主线程空闲时,取出执行事件,从线程池中发起线程执行事件, 当事件执行完成后通知主线程。这就是异步高效的原因。
623 |
624 | var readMe = fs.readFile('readMe.txt', 'utf8', function (err, data) {
625 | fs.writeFile('writeMe.txt', data, function () {
626 | console.log('writeMe has finished')
627 | })
628 | })
629 |
630 | console.log('end')
631 | ```
632 |
633 | ## 7.创建和删除目录
634 |
635 | - [ fs - 文件系统 API 文档](http://nodejs.cn/api/fs.html#fs_fs_unlink_path_callback)
636 |
637 | ```js
638 | var fs = require('fs')
639 |
640 | // 异步删除文件
641 | fs.unlink('writeMe.txt', function () {
642 | console.log('delete writeMe.txt file')
643 | })
644 |
645 | // 同步创建和删除目录
646 | fs.mkdirSync('stuff')
647 | fs.rmdirSync('stuff')
648 |
649 | // 异步
650 | fs.mkdir('stuff', function () {
651 | fs.readFile('readMe.txt', 'utf8', function (err, data) {
652 | fs.writeFile('./stuff/writeMe.txt', data, function () {
653 | console.log('copy successfully')
654 | })
655 | })
656 | })
657 | ```
658 |
659 | ## 8.流和管道
660 |
661 | - 流(stream)
662 | - 处理流式数据的抽象接口
663 | - stream 模块提供了一些基础的 API,用于构建实现了流接口的对象
664 | - 流可以是可读的、可写的、或是可读写的,所有的流都是 EventEmitter 的实例
665 | - 流处理数据通过缓存可以提高性能
666 | # hello-nodejs
667 |
668 | 轻松学 Node.js 基础篇 入门
669 |
670 | 视频地址
671 |
672 | - [https://www.rails365.net](https://www.rails365.net/movies/qing-song-xue-nodejs-ji-chu-pian-1-ke-cheng-jie-shao-yu-kai-fa-huan-jing-da-jian)
673 | - [b站](https://www.bilibili.com/video/av21010015)
674 |
675 | 常用链接
676 |
677 | - [Node.js 官网](https://nodejs.org/zh-cn/)
678 | - [Node.js 中文网](http://nodejs.cn)
679 | - [CNode:Node.js专业中文社区](https://cnodejs.org)
680 |
681 | 看视频整理要点笔记:
682 |
683 | ---
684 |
685 | - [hello-nodejs](#hello-nodejs)
686 | - [1.课程介绍与开发环境搭建](#1%E8%AF%BE%E7%A8%8B%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA)
687 | - [2.全局对象](#2%E5%85%A8%E5%B1%80%E5%AF%B9%E8%B1%A1)
688 |
689 | ---
690 |
691 | ## 1.课程介绍与开发环境搭建
692 |
693 | - 主要包括
694 | - nodejs 基础知识
695 | - web 服务器
696 | - 异步 同步 阻塞 非阻塞
697 |
698 | - 课程基础
699 | - javascript 基础
700 | - html 基础
701 | - 命令行基础
702 |
703 | - Node.js 介绍
704 | - Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境
705 | - Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效
706 | - Node.js 的包管理器 npm,是全球最大的开源库生态系统
707 | - javascript 是脚本语言,需要解析器才能执行,浏览器就充当了解析器
708 | - 在Chrome中,解析器就是 V8 引擎,将 javascript 转换成 机器码
709 | - V8 引擎是开源的,由 C++ 语言编写,性能高
710 | - Node.js 高性能,事件驱动,非阻塞,生态圈很好
711 |
712 | - Node.js 安装
713 | - [官网](https://nodejs.org/zh-cn/) 下载安装即可,很小不到20M!
714 | - 验证是否成功,命令行输入 `node -v` 显示版本号如 `v8.11.4`
715 | - 按提示升级 npm,Update available 5.6.0 → 6.4.1, `npm i -g npm`
716 | - macOS 安装完提示如下
717 |
718 | ```sh
719 | This package has installed:
720 | • Node.js v8.11.4 to /usr/local/bin/node
721 | • npm v5.6.0 to /usr/local/bin/npm
722 | Make sure that /usr/local/bin is in your $PATH.
723 | ```
724 |
725 | - Node.js 用途
726 |
727 | - javascript 运行环境
728 | - 操作文件(grunt gulp webpack)
729 | - 操作数据库
730 | - 写后端 api
731 | - 命令行工具
732 | - web 开发
733 | - 聊天室
734 |
735 | - JavaScript 语句后应该加分号么?
736 | - [知乎讨论](https://www.zhihu.com/question/20298345)
737 | - 代码风格而已,没有定论
738 | - 少分号更易读,不累
739 | - 必须加分号情况很少见:一行开头是括号`(`或者方括号`[`的时候加上分号就可以了,其他时候都不要
740 | - 如果下一行的行首是`( [ / + -`之一的话,js不会自动在上一行句尾加上分号
741 |
742 | ## 2.全局对象
743 |
744 | - 全局对象
745 | - 不用导入,直接使用的对象
746 | - [官方文档](http://nodejs.cn/api/globals.html#globals_global_objects)
747 | - Buffer 类,用于处理二进制数据
748 | - console,用于打印 stdout 和 stderr
749 | - global, 全局的命名空间对象
750 | - process,进程对象
751 | - setTimeout(callback, delay[, ...args])
752 | - setInterval(callback, delay[, ...args])
753 | - setImmediate(callback[, ...args])
754 | - clearTimeout(timeoutObject)
755 | - clearInterval(intervalObject)
756 | - clearImmediate(immediateObject)
757 |
758 | - 以下变量虽然看起来像全局变量,但实际上不是
759 | - 全局变量在所有模块中均可使用
760 | - 以下对象作用域只在模块内,详见 [module文档](http://nodejs.cn/api/modules.html):
761 | - __dirname
762 | - __filename
763 | - exports
764 | - module
765 | - require()
766 |
767 | - 运行 `.js` 脚本文件
768 | - `node app` 或者 `node app.js`
769 |
770 | - 实践代码
771 |
772 | ```js
773 | console.log('hello world');
774 |
775 | setTimeout(function () {
776 | console.log("3 seconds have passed 2");
777 | }, 3000);
778 |
779 | // 箭头函数,es6的写法
780 | setTimeout(() => {
781 | console.log("3 seconds have passed 1");
782 | }, 3000);
783 |
784 | // 每间隔2秒不断执行
785 | setInterval(function () {
786 | console.log("2 seconds have passed");
787 | }, 2000);
788 |
789 |
790 | var time = 0
791 | var timer = setInterval(function () {
792 | time += 2;
793 | console.log(time + " seconds have passed");
794 | if (time > 6) {
795 | clearInterval(timer);
796 | console.log("clearInterval")
797 | }
798 | }, 2000)
799 |
800 | // 输出当前目录 和 带绝对路径的文件名
801 | console.log(__dirname)
802 | console.log(__filename)
803 |
804 | console.log('end')
805 | console.dir(global)
806 | ```
807 |
808 | ## 3.回调函数
809 |
810 | ```js
811 | function sayHi() {
812 | console.log('Hi')
813 | }
814 |
815 | sayHi() // 调用函数
816 |
817 | // 将匿名函数赋给变量
818 | var sayBye = function (name) {
819 | console.log(name + ' Bye')
820 | }
821 |
822 | sayBye()
823 |
824 | // 第一个参数是函数
825 | function callFunction(fun, name) {
826 | fun(name)
827 | }
828 |
829 | callFunction(sayBye, 'able')
830 | // 或者
831 | callFunction(function (name) {
832 | console.log(name + ' Bye')
833 | }, 'able')
834 | ```
835 |
836 | ## 4.模块
837 |
838 | - module 对象
839 | - 每个文件都被视为独立的模块
840 | - 每个模块中,module 指向表示当前模块的对象的引用
841 | - module 实际上不是全局的,而是每个模块本地的
842 | - module.exports 导出模块内的对象,方便其他对象引用
843 | - require() 引入模块
844 | - 当 Node.js 直接运行一个文件时,require.main 会被设为它的 module
845 | - 可以通过 require.main === module 来判断一个文件是否被直接运行
846 | - module 提供了一个 filename 属性(通常等同于 __filename)
847 | - 可以通过检查 require.main.filename 来获取当前应用程序的入口点
848 |
849 | ```js
850 | // counter.js
851 | var counter = function (arr) {
852 | return "There are " + arr.length + " elements in array"
853 | }
854 |
855 | var adder = function (a, b) {
856 | return `the sum of the 2 numbers is ${a+b}`
857 | }
858 |
859 | var pi = 3.14
860 |
861 | // 只有一个时可以这样导入
862 | // module.exports = counter
863 |
864 | /*
865 | module.exports.counter = counter
866 | module.exports.adder = adder
867 | module.exports.pi = pi
868 | */
869 |
870 | module.exports = {
871 | counter: counter,
872 | adder: adder,
873 | pi: pi,
874 | }
875 | /* 对象可以简写
876 | module.exports = {
877 | counter,
878 | adder,
879 | pi,
880 | }
881 | */
882 |
883 | //p4.js
884 | var stuff = require('./count')
885 |
886 | console.log(stuff.counter(['ruby', 'nodejs', 'react']))
887 | console.log(stuff.adder(3, 2))
888 | console.log(stuff.pi)
889 | ```
890 |
891 | ## 5.事件 events
892 |
893 | - 多数 Node.js 核心 API 都采用异步事件驱动架构
894 | - 所有能触发事件的对象都是 EventEmitter 类的实例
895 | - 事件名称通常是驼峰式的字符串
896 |
897 | - 实践代码
898 |
899 | ```js
900 | var events = require('events')
901 | var util = require('util')
902 |
903 | // 事件 对象
904 | var myEmitter = new events.EventEmitter()
905 |
906 | // 绑定 事件名称 和 回调函数
907 | myEmitter.on('someEvent', function (message) {
908 | console.log(message)
909 | })
910 |
911 | // 触发实践,使用事件名称
912 | myEmitter.emit('someEvent', 'The event was emitted')
913 |
914 | // 创建对象
915 | var Person = function (name) {
916 | this.name = name
917 | }
918 |
919 | // 继承,让Person类具有事件对象的特性,绑定和触发事件
920 | util.inherits(Person, events.EventEmitter)
921 | // 新建对象
922 | var xiaoming = new Person('xiaoming')
923 | var lili = new Person('lili')
924 |
925 | var person = [xiaoming, lili]
926 |
927 | // 循环person数组,绑定事件
928 | person.forEach(function (person) {
929 | person.on('speak', function (message) {
930 | console.log(person.name + ' said: ' + message)
931 | })
932 | })
933 |
934 | // 触发事件
935 | xiaoming.emit('speak', 'hi')
936 | lili.emit('speak', 'I want a curry')
937 | ```
938 |
939 | ## 6.读写文件(同步和异步)
940 |
941 | ```js
942 | var fs = require('fs')
943 |
944 | // 同步读写文件,顺序执行,如果读取时间很长,会阻塞进程
945 | var readMe = fs.readFileSync('readMe.txt', 'utf8')
946 | fs.writeFileSync('writeMe.txt', readMe)
947 |
948 | console.log(readMe)
949 | console.log('finished sync')
950 |
951 | // 异步读写文件
952 | // 异步事件,Nodejs 维护一个事件队列,注册事件,完成后执行主线程
953 | // 当主线程空闲时,取出执行事件,从线程池中发起线程执行事件, 当事件执行完成后通知主线程。这就是异步高效的原因。
954 |
955 | var readMe = fs.readFile('readMe.txt', 'utf8', function (err, data) {
956 | fs.writeFile('writeMe.txt', data, function () {
957 | console.log('writeMe has finished')
958 | })
959 | })
960 |
961 | console.log('end')
962 | ```
963 |
964 | ## 7.创建和删除目录
965 |
966 | - [ fs - 文件系统 API 文档](http://nodejs.cn/api/fs.html#fs_fs_unlink_path_callback)
967 |
968 | ```js
969 | var fs = require('fs')
970 |
971 | // 异步删除文件
972 | fs.unlink('writeMe.txt', function () {
973 | console.log('delete writeMe.txt file')
974 | })
975 |
976 | // 同步创建和删除目录
977 | fs.mkdirSync('stuff')
978 | fs.rmdirSync('stuff')
979 |
980 | // 异步
981 | fs.mkdir('stuff', function () {
982 | fs.readFile('readMe.txt', 'utf8', function (err, data) {
983 | fs.writeFile('./stuff/writeMe.txt', data, function () {
984 | console.log('copy successfully')
985 | })
986 | })
987 | })
988 | ```
989 |
990 | ## 8.流和管道
991 |
992 | - 流(stream)
993 | - 处理流式数据的抽象接口
994 | - stream 模块提供了一些基础的 API,用于构建实现了流接口的对象
995 | - 流可以是可读的、可写的、或是可读写的,所有的流都是 EventEmitter 的实例
996 | - 流处理数据通过缓存可以提高性能
997 | # hello-nodejs
998 |
999 | 轻松学 Node.js 基础篇 入门
1000 |
1001 | 视频地址
1002 |
1003 | - [https://www.rails365.net](https://www.rails365.net/movies/qing-song-xue-nodejs-ji-chu-pian-1-ke-cheng-jie-shao-yu-kai-fa-huan-jing-da-jian)
1004 | - [b站](https://www.bilibili.com/video/av21010015)
1005 |
1006 | 常用链接
1007 |
1008 | - [Node.js 官网](https://nodejs.org/zh-cn/)
1009 | - [Node.js 中文网](http://nodejs.cn)
1010 | - [CNode:Node.js专业中文社区](https://cnodejs.org)
1011 |
1012 | 看视频整理要点笔记:
1013 |
1014 | ---
1015 |
1016 | - [hello-nodejs](#hello-nodejs)
1017 | - [1.课程介绍与开发环境搭建](#1%E8%AF%BE%E7%A8%8B%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA)
1018 | - [2.全局对象](#2%E5%85%A8%E5%B1%80%E5%AF%B9%E8%B1%A1)
1019 |
1020 | ---
1021 |
1022 | ## 1.课程介绍与开发环境搭建
1023 |
1024 | - 主要包括
1025 | - nodejs 基础知识
1026 | - web 服务器
1027 | - 异步 同步 阻塞 非阻塞
1028 |
1029 | - 课程基础
1030 | - javascript 基础
1031 | - html 基础
1032 | - 命令行基础
1033 |
1034 | - Node.js 介绍
1035 | - Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境
1036 | - Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效
1037 | - Node.js 的包管理器 npm,是全球最大的开源库生态系统
1038 | - javascript 是脚本语言,需要解析器才能执行,浏览器就充当了解析器
1039 | - 在Chrome中,解析器就是 V8 引擎,将 javascript 转换成 机器码
1040 | - V8 引擎是开源的,由 C++ 语言编写,性能高
1041 | - Node.js 高性能,事件驱动,非阻塞,生态圈很好
1042 |
1043 | - Node.js 安装
1044 | - [官网](https://nodejs.org/zh-cn/) 下载安装即可,很小不到20M!
1045 | - 验证是否成功,命令行输入 `node -v` 显示版本号如 `v8.11.4`
1046 | - 按提示升级 npm,Update available 5.6.0 → 6.4.1, `npm i -g npm`
1047 | - macOS 安装完提示如下
1048 |
1049 | ```sh
1050 | This package has installed:
1051 | • Node.js v8.11.4 to /usr/local/bin/node
1052 | • npm v5.6.0 to /usr/local/bin/npm
1053 | Make sure that /usr/local/bin is in your $PATH.
1054 | ```
1055 |
1056 | - Node.js 用途
1057 |
1058 | - javascript 运行环境
1059 | - 操作文件(grunt gulp webpack)
1060 | - 操作数据库
1061 | - 写后端 api
1062 | - 命令行工具
1063 | - web 开发
1064 | - 聊天室
1065 |
1066 | - JavaScript 语句后应该加分号么?
1067 | - [知乎讨论](https://www.zhihu.com/question/20298345)
1068 | - 代码风格而已,没有定论
1069 | - 少分号更易读,不累
1070 | - 必须加分号情况很少见:一行开头是括号`(`或者方括号`[`的时候加上分号就可以了,其他时候都不要
1071 | - 如果下一行的行首是`( [ / + -`之一的话,js不会自动在上一行句尾加上分号
1072 |
1073 | ## 2.全局对象
1074 |
1075 | - 全局对象
1076 | - 不用导入,直接使用的对象
1077 | - [官方文档](http://nodejs.cn/api/globals.html#globals_global_objects)
1078 | - Buffer 类,用于处理二进制数据
1079 | - console,用于打印 stdout 和 stderr
1080 | - global, 全局的命名空间对象
1081 | - process,进程对象
1082 | - setTimeout(callback, delay[, ...args])
1083 | - setInterval(callback, delay[, ...args])
1084 | - setImmediate(callback[, ...args])
1085 | - clearTimeout(timeoutObject)
1086 | - clearInterval(intervalObject)
1087 | - clearImmediate(immediateObject)
1088 |
1089 | - 以下变量虽然看起来像全局变量,但实际上不是
1090 | - 全局变量在所有模块中均可使用
1091 | - 以下对象作用域只在模块内,详见 [module文档](http://nodejs.cn/api/modules.html):
1092 | - __dirname
1093 | - __filename
1094 | - exports
1095 | - module
1096 | - require()
1097 |
1098 | - 运行 `.js` 脚本文件
1099 | - `node app` 或者 `node app.js`
1100 |
1101 | - 实践代码
1102 |
1103 | ```js
1104 | console.log('hello world');
1105 |
1106 | setTimeout(function () {
1107 | console.log("3 seconds have passed 2");
1108 | }, 3000);
1109 |
1110 | // 箭头函数,es6的写法
1111 | setTimeout(() => {
1112 | console.log("3 seconds have passed 1");
1113 | }, 3000);
1114 |
1115 | // 每间隔2秒不断执行
1116 | setInterval(function () {
1117 | console.log("2 seconds have passed");
1118 | }, 2000);
1119 |
1120 |
1121 | var time = 0
1122 | var timer = setInterval(function () {
1123 | time += 2;
1124 | console.log(time + " seconds have passed");
1125 | if (time > 6) {
1126 | clearInterval(timer);
1127 | console.log("clearInterval")
1128 | }
1129 | }, 2000)
1130 |
1131 | // 输出当前目录 和 带绝对路径的文件名
1132 | console.log(__dirname)
1133 | console.log(__filename)
1134 |
1135 | console.log('end')
1136 | console.dir(global)
1137 | ```
1138 |
1139 | ## 3.回调函数
1140 |
1141 | ```js
1142 | function sayHi() {
1143 | console.log('Hi')
1144 | }
1145 |
1146 | sayHi() // 调用函数
1147 |
1148 | // 将匿名函数赋给变量
1149 | var sayBye = function (name) {
1150 | console.log(name + ' Bye')
1151 | }
1152 |
1153 | sayBye()
1154 |
1155 | // 第一个参数是函数
1156 | function callFunction(fun, name) {
1157 | fun(name)
1158 | }
1159 |
1160 | callFunction(sayBye, 'able')
1161 | // 或者
1162 | callFunction(function (name) {
1163 | console.log(name + ' Bye')
1164 | }, 'able')
1165 | ```
1166 |
1167 | ## 4.模块
1168 |
1169 | - module 对象
1170 | - 每个文件都被视为独立的模块
1171 | - 每个模块中,module 指向表示当前模块的对象的引用
1172 | - module 实际上不是全局的,而是每个模块本地的
1173 | - module.exports 导出模块内的对象,方便其他对象引用
1174 | - require() 引入模块
1175 | - 当 Node.js 直接运行一个文件时,require.main 会被设为它的 module
1176 | - 可以通过 require.main === module 来判断一个文件是否被直接运行
1177 | - module 提供了一个 filename 属性(通常等同于 __filename)
1178 | - 可以通过检查 require.main.filename 来获取当前应用程序的入口点
1179 |
1180 | ```js
1181 | // counter.js
1182 | var counter = function (arr) {
1183 | return "There are " + arr.length + " elements in array"
1184 | }
1185 |
1186 | var adder = function (a, b) {
1187 | return `the sum of the 2 numbers is ${a+b}`
1188 | }
1189 |
1190 | var pi = 3.14
1191 |
1192 | // 只有一个时可以这样导入
1193 | // module.exports = counter
1194 |
1195 | /*
1196 | module.exports.counter = counter
1197 | module.exports.adder = adder
1198 | module.exports.pi = pi
1199 | */
1200 |
1201 | module.exports = {
1202 | counter: counter,
1203 | adder: adder,
1204 | pi: pi,
1205 | }
1206 | /* 对象可以简写
1207 | module.exports = {
1208 | counter,
1209 | adder,
1210 | pi,
1211 | }
1212 | */
1213 |
1214 | //p4.js
1215 | var stuff = require('./count')
1216 |
1217 | console.log(stuff.counter(['ruby', 'nodejs', 'react']))
1218 | console.log(stuff.adder(3, 2))
1219 | console.log(stuff.pi)
1220 | ```
1221 |
1222 | ## 5.事件 events
1223 |
1224 | - 多数 Node.js 核心 API 都采用异步事件驱动架构
1225 | - 所有能触发事件的对象都是 EventEmitter 类的实例
1226 | - 事件名称通常是驼峰式的字符串
1227 |
1228 | - 实践代码
1229 |
1230 | ```js
1231 | var events = require('events')
1232 | var util = require('util')
1233 |
1234 | // 事件 对象
1235 | var myEmitter = new events.EventEmitter()
1236 |
1237 | // 绑定 事件名称 和 回调函数
1238 | myEmitter.on('someEvent', function (message) {
1239 | console.log(message)
1240 | })
1241 |
1242 | // 触发实践,使用事件名称
1243 | myEmitter.emit('someEvent', 'The event was emitted')
1244 |
1245 | // 创建对象
1246 | var Person = function (name) {
1247 | this.name = name
1248 | }
1249 |
1250 | // 继承,让Person类具有事件对象的特性,绑定和触发事件
1251 | util.inherits(Person, events.EventEmitter)
1252 | // 新建对象
1253 | var xiaoming = new Person('xiaoming')
1254 | var lili = new Person('lili')
1255 |
1256 | var person = [xiaoming, lili]
1257 |
1258 | // 循环person数组,绑定事件
1259 | person.forEach(function (person) {
1260 | person.on('speak', function (message) {
1261 | console.log(person.name + ' said: ' + message)
1262 | })
1263 | })
1264 |
1265 | // 触发事件
1266 | xiaoming.emit('speak', 'hi')
1267 | lili.emit('speak', 'I want a curry')
1268 | ```
1269 |
1270 | ## 6.读写文件(同步和异步)
1271 |
1272 | ```js
1273 | var fs = require('fs')
1274 |
1275 | // 同步读写文件,顺序执行,如果读取时间很长,会阻塞进程
1276 | var readMe = fs.readFileSync('readMe.txt', 'utf8')
1277 | fs.writeFileSync('writeMe.txt', readMe)
1278 |
1279 | console.log(readMe)
1280 | console.log('finished sync')
1281 |
1282 | // 异步读写文件
1283 | // 异步事件,Nodejs 维护一个事件队列,注册事件,完成后执行主线程
1284 | // 当主线程空闲时,取出执行事件,从线程池中发起线程执行事件, 当事件执行完成后通知主线程。这就是异步高效的原因。
1285 |
1286 | var readMe = fs.readFile('readMe.txt', 'utf8', function (err, data) {
1287 | fs.writeFile('writeMe.txt', data, function () {
1288 | console.log('writeMe has finished')
1289 | })
1290 | })
1291 |
1292 | console.log('end')
1293 | ```
1294 |
1295 | ## 7.创建和删除目录
1296 |
1297 | - [ fs - 文件系统 API 文档](http://nodejs.cn/api/fs.html#fs_fs_unlink_path_callback)
1298 |
1299 | ```js
1300 | var fs = require('fs')
1301 |
1302 | // 异步删除文件
1303 | fs.unlink('writeMe.txt', function () {
1304 | console.log('delete writeMe.txt file')
1305 | })
1306 |
1307 | // 同步创建和删除目录
1308 | fs.mkdirSync('stuff')
1309 | fs.rmdirSync('stuff')
1310 |
1311 | // 异步
1312 | fs.mkdir('stuff', function () {
1313 | fs.readFile('readMe.txt', 'utf8', function (err, data) {
1314 | fs.writeFile('./stuff/writeMe.txt', data, function () {
1315 | console.log('copy successfully')
1316 | })
1317 | })
1318 | })
1319 | ```
1320 |
1321 | ## 8.流和管道
1322 |
1323 | - 流(stream)
1324 | - 处理流式数据的抽象接口
1325 | - stream 模块提供了一些基础的 API,用于构建实现了流接口的对象
1326 | - 流可以是可读的、可写的、或是可读写的,所有的流都是 EventEmitter 的实例
1327 | - 流处理数据通过缓存可以提高性能
1328 | # hello-nodejs
1329 |
1330 | 轻松学 Node.js 基础篇 入门
1331 |
1332 | 视频地址
1333 |
1334 | - [https://www.rails365.net](https://www.rails365.net/movies/qing-song-xue-nodejs-ji-chu-pian-1-ke-cheng-jie-shao-yu-kai-fa-huan-jing-da-jian)
1335 | - [b站](https://www.bilibili.com/video/av21010015)
1336 |
1337 | 常用链接
1338 |
1339 | - [Node.js 官网](https://nodejs.org/zh-cn/)
1340 | - [Node.js 中文网](http://nodejs.cn)
1341 | - [CNode:Node.js专业中文社区](https://cnodejs.org)
1342 |
1343 | 看视频整理要点笔记:
1344 |
1345 | ---
1346 |
1347 | - [hello-nodejs](#hello-nodejs)
1348 | - [1.课程介绍与开发环境搭建](#1%E8%AF%BE%E7%A8%8B%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA)
1349 | - [2.全局对象](#2%E5%85%A8%E5%B1%80%E5%AF%B9%E8%B1%A1)
1350 |
1351 | ---
1352 |
1353 | ## 1.课程介绍与开发环境搭建
1354 |
1355 | - 主要包括
1356 | - nodejs 基础知识
1357 | - web 服务器
1358 | - 异步 同步 阻塞 非阻塞
1359 |
1360 | - 课程基础
1361 | - javascript 基础
1362 | - html 基础
1363 | - 命令行基础
1364 |
1365 | - Node.js 介绍
1366 | - Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境
1367 | - Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效
1368 | - Node.js 的包管理器 npm,是全球最大的开源库生态系统
1369 | - javascript 是脚本语言,需要解析器才能执行,浏览器就充当了解析器
1370 | - 在Chrome中,解析器就是 V8 引擎,将 javascript 转换成 机器码
1371 | - V8 引擎是开源的,由 C++ 语言编写,性能高
1372 | - Node.js 高性能,事件驱动,非阻塞,生态圈很好
1373 |
1374 | - Node.js 安装
1375 | - [官网](https://nodejs.org/zh-cn/) 下载安装即可,很小不到20M!
1376 | - 验证是否成功,命令行输入 `node -v` 显示版本号如 `v8.11.4`
1377 | - 按提示升级 npm,Update available 5.6.0 → 6.4.1, `npm i -g npm`
1378 | - macOS 安装完提示如下
1379 |
1380 | ```sh
1381 | This package has installed:
1382 | • Node.js v8.11.4 to /usr/local/bin/node
1383 | • npm v5.6.0 to /usr/local/bin/npm
1384 | Make sure that /usr/local/bin is in your $PATH.
1385 | ```
1386 |
1387 | - Node.js 用途
1388 |
1389 | - javascript 运行环境
1390 | - 操作文件(grunt gulp webpack)
1391 | - 操作数据库
1392 | - 写后端 api
1393 | - 命令行工具
1394 | - web 开发
1395 | - 聊天室
1396 |
1397 | - JavaScript 语句后应该加分号么?
1398 | - [知乎讨论](https://www.zhihu.com/question/20298345)
1399 | - 代码风格而已,没有定论
1400 | - 少分号更易读,不累
1401 | - 必须加分号情况很少见:一行开头是括号`(`或者方括号`[`的时候加上分号就可以了,其他时候都不要
1402 | - 如果下一行的行首是`( [ / + -`之一的话,js不会自动在上一行句尾加上分号
1403 |
1404 | ## 2.全局对象
1405 |
1406 | - 全局对象
1407 | - 不用导入,直接使用的对象
1408 | - [官方文档](http://nodejs.cn/api/globals.html#globals_global_objects)
1409 | - Buffer 类,用于处理二进制数据
1410 | - console,用于打印 stdout 和 stderr
1411 | - global, 全局的命名空间对象
1412 | - process,进程对象
1413 | - setTimeout(callback, delay[, ...args])
1414 | - setInterval(callback, delay[, ...args])
1415 | - setImmediate(callback[, ...args])
1416 | - clearTimeout(timeoutObject)
1417 | - clearInterval(intervalObject)
1418 | - clearImmediate(immediateObject)
1419 |
1420 | - 以下变量虽然看起来像全局变量,但实际上不是
1421 | - 全局变量在所有模块中均可使用
1422 | - 以下对象作用域只在模块内,详见 [module文档](http://nodejs.cn/api/modules.html):
1423 | - __dirname
1424 | - __filename
1425 | - exports
1426 | - module
1427 | - require()
1428 |
1429 | - 运行 `.js` 脚本文件
1430 | - `node app` 或者 `node app.js`
1431 |
1432 | - 实践代码
1433 |
1434 | ```js
1435 | console.log('hello world');
1436 |
1437 | setTimeout(function () {
1438 | console.log("3 seconds have passed 2");
1439 | }, 3000);
1440 |
1441 | // 箭头函数,es6的写法
1442 | setTimeout(() => {
1443 | console.log("3 seconds have passed 1");
1444 | }, 3000);
1445 |
1446 | // 每间隔2秒不断执行
1447 | setInterval(function () {
1448 | console.log("2 seconds have passed");
1449 | }, 2000);
1450 |
1451 |
1452 | var time = 0
1453 | var timer = setInterval(function () {
1454 | time += 2;
1455 | console.log(time + " seconds have passed");
1456 | if (time > 6) {
1457 | clearInterval(timer);
1458 | console.log("clearInterval")
1459 | }
1460 | }, 2000)
1461 |
1462 | // 输出当前目录 和 带绝对路径的文件名
1463 | console.log(__dirname)
1464 | console.log(__filename)
1465 |
1466 | console.log('end')
1467 | console.dir(global)
1468 | ```
1469 |
1470 | ## 3.回调函数
1471 |
1472 | ```js
1473 | function sayHi() {
1474 | console.log('Hi')
1475 | }
1476 |
1477 | sayHi() // 调用函数
1478 |
1479 | // 将匿名函数赋给变量
1480 | var sayBye = function (name) {
1481 | console.log(name + ' Bye')
1482 | }
1483 |
1484 | sayBye()
1485 |
1486 | // 第一个参数是函数
1487 | function callFunction(fun, name) {
1488 | fun(name)
1489 | }
1490 |
1491 | callFunction(sayBye, 'able')
1492 | // 或者
1493 | callFunction(function (name) {
1494 | console.log(name + ' Bye')
1495 | }, 'able')
1496 | ```
1497 |
1498 | ## 4.模块
1499 |
1500 | - module 对象
1501 | - 每个文件都被视为独立的模块
1502 | - 每个模块中,module 指向表示当前模块的对象的引用
1503 | - module 实际上不是全局的,而是每个模块本地的
1504 | - module.exports 导出模块内的对象,方便其他对象引用
1505 | - require() 引入模块
1506 | - 当 Node.js 直接运行一个文件时,require.main 会被设为它的 module
1507 | - 可以通过 require.main === module 来判断一个文件是否被直接运行
1508 | - module 提供了一个 filename 属性(通常等同于 __filename)
1509 | - 可以通过检查 require.main.filename 来获取当前应用程序的入口点
1510 |
1511 | ```js
1512 | // counter.js
1513 | var counter = function (arr) {
1514 | return "There are " + arr.length + " elements in array"
1515 | }
1516 |
1517 | var adder = function (a, b) {
1518 | return `the sum of the 2 numbers is ${a+b}`
1519 | }
1520 |
1521 | var pi = 3.14
1522 |
1523 | // 只有一个时可以这样导入
1524 | // module.exports = counter
1525 |
1526 | /*
1527 | module.exports.counter = counter
1528 | module.exports.adder = adder
1529 | module.exports.pi = pi
1530 | */
1531 |
1532 | module.exports = {
1533 | counter: counter,
1534 | adder: adder,
1535 | pi: pi,
1536 | }
1537 | /* 对象可以简写
1538 | module.exports = {
1539 | counter,
1540 | adder,
1541 | pi,
1542 | }
1543 | */
1544 |
1545 | //p4.js
1546 | var stuff = require('./count')
1547 |
1548 | console.log(stuff.counter(['ruby', 'nodejs', 'react']))
1549 | console.log(stuff.adder(3, 2))
1550 | console.log(stuff.pi)
1551 | ```
1552 |
1553 | ## 5.事件 events
1554 |
1555 | - 多数 Node.js 核心 API 都采用异步事件驱动架构
1556 | - 所有能触发事件的对象都是 EventEmitter 类的实例
1557 | - 事件名称通常是驼峰式的字符串
1558 |
1559 | - 实践代码
1560 |
1561 | ```js
1562 | var events = require('events')
1563 | var util = require('util')
1564 |
1565 | // 事件 对象
1566 | var myEmitter = new events.EventEmitter()
1567 |
1568 | // 绑定 事件名称 和 回调函数
1569 | myEmitter.on('someEvent', function (message) {
1570 | console.log(message)
1571 | })
1572 |
1573 | // 触发实践,使用事件名称
1574 | myEmitter.emit('someEvent', 'The event was emitted')
1575 |
1576 | // 创建对象
1577 | var Person = function (name) {
1578 | this.name = name
1579 | }
1580 |
1581 | // 继承,让Person类具有事件对象的特性,绑定和触发事件
1582 | util.inherits(Person, events.EventEmitter)
1583 | // 新建对象
1584 | var xiaoming = new Person('xiaoming')
1585 | var lili = new Person('lili')
1586 |
1587 | var person = [xiaoming, lili]
1588 |
1589 | // 循环person数组,绑定事件
1590 | person.forEach(function (person) {
1591 | person.on('speak', function (message) {
1592 | console.log(person.name + ' said: ' + message)
1593 | })
1594 | })
1595 |
1596 | // 触发事件
1597 | xiaoming.emit('speak', 'hi')
1598 | lili.emit('speak', 'I want a curry')
1599 | ```
1600 |
1601 | ## 6.读写文件(同步和异步)
1602 |
1603 | ```js
1604 | var fs = require('fs')
1605 |
1606 | // 同步读写文件,顺序执行,如果读取时间很长,会阻塞进程
1607 | var readMe = fs.readFileSync('readMe.txt', 'utf8')
1608 | fs.writeFileSync('writeMe.txt', readMe)
1609 |
1610 | console.log(readMe)
1611 | console.log('finished sync')
1612 |
1613 | // 异步读写文件
1614 | // 异步事件,Nodejs 维护一个事件队列,注册事件,完成后执行主线程
1615 | // 当主线程空闲时,取出执行事件,从线程池中发起线程执行事件, 当事件执行完成后通知主线程。这就是异步高效的原因。
1616 |
1617 | var readMe = fs.readFile('readMe.txt', 'utf8', function (err, data) {
1618 | fs.writeFile('writeMe.txt', data, function () {
1619 | console.log('writeMe has finished')
1620 | })
1621 | })
1622 |
1623 | console.log('end')
1624 | ```
1625 |
1626 | ## 7.创建和删除目录
1627 |
1628 | - [ fs - 文件系统 API 文档](http://nodejs.cn/api/fs.html#fs_fs_unlink_path_callback)
1629 |
1630 | ```js
1631 | var fs = require('fs')
1632 |
1633 | // 异步删除文件
1634 | fs.unlink('writeMe.txt', function () {
1635 | console.log('delete writeMe.txt file')
1636 | })
1637 |
1638 | // 同步创建和删除目录
1639 | fs.mkdirSync('stuff')
1640 | fs.rmdirSync('stuff')
1641 |
1642 | // 异步
1643 | fs.mkdir('stuff', function () {
1644 | fs.readFile('readMe.txt', 'utf8', function (err, data) {
1645 | fs.writeFile('./stuff/writeMe.txt', data, function () {
1646 | console.log('copy successfully')
1647 | })
1648 | })
1649 | })
1650 | ```
1651 |
1652 | ## 8.流和管道
1653 |
1654 | - 流(stream)
1655 | - 处理流式数据的抽象接口
1656 | - stream 模块提供了一些基础的 API,用于构建实现了流接口的对象
1657 | - 流可以是可读的、可写的、或是可读写的,所有的流都是 EventEmitter 的实例
1658 | - 流处理数据通过缓存可以提高性能
1659 |
1660 |
--------------------------------------------------------------------------------