nodejs学习笔记

Posted by Youzi on March 28, 2021

前言

记录 nodejs 学习进程。

基础

nodejs是运行在服务端的基于 ChromeV8 引擎服务端脚本语言,这些基础的概念就不谈了,进入正题;

认识全局变量

  • __filename:当前运行脚本文件所在位置;
  • __dirname:当前运行脚本的目录;
  • process:进程对象;
    • kill:杀进程的函数方法;
    • exit:退出脚本的方法;
    • cpuUsage:脚本占用的 cpu 使用率;
    • memoryUsage:内存使用率;
    • env:脚本运行的环境变量;
    • argv:脚本启动时,用户输入的命令;

commonJS 模块规范

  • exports:一个对象,在这个对象上添加属性,就可以让外部模块引用到该属性;注意不要去修改这个对象本身;
  • module.exports:对这个属性直接赋值,会覆盖上面的exports,并且在外部引用时,不需要用属性的方式,而直接是导出的对象(或者是任意的基本类型和其他引用类型),类似 ES6 里面的export default
  • require:引入模块的方法,语法上可以当成是一个函数,返回值是导出的内容,参数是引用的文件路径。
1
2
3
4
5
6
7
8
9
// inner.js
module.exports = function test() {
  console.log('test)
};

// outer.js
const fun = require('inner.js');
fun();
// test

webpack 实现模块化的方式

在 JS 中,为了要创建作用域,一般都会通过声明函数的方式来创建一个块级作用域,在 webpack 中,打包过程为每个文件模块都创建了一个函数,从而实现每个文件的内部作用域。

webpack 会为每个文件都执行一次webpack_require这么一个函数,接收文件路径作为参数;

在函数体内,首先会去 check 这个文件是否已经引入过了(相当于做了模块的缓存),如果没有被引入过,则创建一个对象,并在installedModules这个全局变量上添加这个对象作为一个属性,该对象的 key 就是路径;

再来说说创建的这个对象,这个对象在函数内部命名为module,有三个属性,其中有一个属性是exports,初始时它是一个空对象;随后 webpack 就执行模块代码;

这里要解释一下什么是执行模块代码,webpack 会把模块内部的代码,封装成一个函数,函数接收两个参数,module, exports,正好对应了我们在子模块代码里用到的两个变量,其中,module是上面提到的创建的对象,exports是创建的对象内部的一个属性,所以其实exports相当于一个module.exports的引用;

这个函数还没讲完,在函数体内部,是一个eval函数,我在编译后的代码中看到webpack把子模块里的代码都转换成了字符串,该字符串作为eval函数的参数,执行了一遍模块代码(也有通过call方法去执行的);

所以我们如果在子模块里改变了module.exports这个对象的引用,那么这个对象指向的内存地址就是新的可以被外部模块接收的;而exports这个变量指向的对象就还是原来的内存地址,就不会被外部所接收了;

总结来说,外部模块引用的始终是module.exports这个对象指向的内存地址;

从命令行接收和输出到命令行

前面提到过在全局变量进程process里有一个argv的参数,就表示了用户在命令行输入的全部参数,它是一个数组,前两个元素是固定的,第一个是node命令的完整路径,第二个参数是正在被执行的文件的完整路径;后续的元素就是用户输入的参数列表;另外 nodejs 提供了minimist库,调用这个库可以让程序更简单的获取到具体key对应的value,与普通方式不同的是要求命令行输入用--符号来标识一对key-value

常用实例:

1
2
3
4
5
6
7
8
9
10
// node app.js arg1
const args = process.argv.slice(2);
console.log(args[0]);
// arg1

// 用minimist库
// node app.js --arg1=10
const args = require('minimist')(process.argv.slice(2));
console.log(args['arg1']);
// 10

非阻塞 I/O

  • I/O 即输入输出;
  • 阻塞 I/O 和非阻塞 I/O 的区别在于,系统接收输入再到输出期间,能不能接收其他输入

理解要点:

  1. 确定一个进行 I/O 的系统;
  2. 思考在 I/O 过程中,能不能进行其他的 I/O。