[学习笔记] - Node.js

Node.js是个神奇的东西,当初通过python的爬虫学习到了JavaScrip(爬虫的本质就是JS),但是到最近Node.js的出现越来越频繁,本身JavaScrip的大量使用也间接导致了Node.js的大量使用,于是回到当年遇见JavaScrip就不会爬虫的那时,是时候把Node.js过一遍了。

注释

对于JS的语法不会在这里描写,Node.js的按照等也不会进行描述。更多的注重Node.js的独有的特点。

Node.js是什么

Node.js不是一门编程语言,也不是一个框架它是JavaScript的执行环境(runtime environment),本身JavaScript只能在浏览器上执行,比如:FireFox,Chrome,Edge。每个浏览器都有不同的JavaScript引擎,把它翻译为机器代码来执行,而Node.js就是把Chrome的JS引擎拿了过来,同时加上了更多的功能(比如读取文件),于是Node.js就诞生了

Node.js的本质是让JavaScript可以脱离浏览器运行

  • 服务器端JavaScript处理:server-side JavaScript execution
  • 非阻断/异步I/O:non-blocking or asynchronous I/O
  • 事件驱动:Event-driven

Node.js是一个服务器端的、非阻断式I/O的、事件驱动的JavaScript运行环境。

Node.js的全局变量

在浏览器里,有windows,在Node.js里,有global,但是不同在于

在浏览器里,每定义一个全局的变量,可以通过windows去调用它,如windows.foo(),但是在Node.js里,这样并不成立,因为我们需要JavaScript能够模块化

  • 每个在Node.js App项目的文件都被视作一个模块
  • 每个Node.js App项目都至少有个模块,即main模块
  • 每个模块都是私有的,需要暴露出去才能给其他模块使用

对于其他模块,可以通过这样的方式暴露出接口

1
module.exports = foo;

Node.js并不会直接执行模块里面的代码,而是讲模块里面的代码封装在一个函数(Mudule Warpper Funciton)里面,如下

1
2
3
(function (exports, require, module, __filename, __dirname) {
...
})

Node.js官方库

就如python一样,Node.js也有许多自带的模块

Node.js事件

Node.js 是单进程单线程应用程序

  • Node.js 几乎每一个 API 都是支持回调函数的。
  • Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现。

对于事件的基本理解,如果开发过MC的插件啥的话就会很好理解,这里不做多的解释,搜索可以获得更多更好的解释。Node.js可以触发事件,事先需要注册一个监听器,其本质是一个回调函数。如下实现:

1
2
3
4
5
6
7
8
9
10
// event class
const EventEmitter = require('events');
// instance
var emitter = new EventEmitter();
// register a listener
emitter.on('event_name', function () {
console.log('event called');
});
// raise an event
emitter.emit('event_name');
  • 每一个实例emitter都是互不相关的
  • 可以通过类继承EventEmitter实现对一个emitter的封装
1
2
3
4
5
6
7
8
9
10
11
class MyEvent extends EventEmitter {
foo() {
this.emit('event');
}
}

var myemitter = new MyEvent();
myemitter.on('event', function () {
console.log('event called');
});
myemitter.emit('event');

事件传参

一般对象进行包装,进行多个参数的传递

1
2
3
4
5
6
7
// register a listener
emitter.on('event_name', (arg) => {
console.log('event called', arg);
});

// raise an event
emitter.emit('event_name', {param1: 'param1', param2: 'param2'});