文本将介绍 Node.js 的安装以及基本知识,包括 Node.js 如何运行 JS 代码,Node.js 与浏览器上 API 的区别,以及 Node.js 中如何应用模块化,同时深入探讨模块在两种数据暴露两种方式上的区别。
Node.js 介绍
Node.js® is a free, open-source, cross-platform JavaScript runtime environment that lets developers create servers, web apps, command line tools and scripts.
Node.js 是一个开源的,跨平台的 JavaScript 运行环境,它能够让开发者创建服务端,web应用,命令行工具以及脚本。
安装 Node.js
- 进入官网下载页:nodejs.org/en/download
- 下载安装包,安装Node.js
- 等待安装,直到安装成功
- 验证是否完成安装
node -v
- 出现以下信息即代表 node.js 安装成功
v20.12.0
Node.js 运行 js 文件
Node.js 是一个 JS 运行环境,因此可以通过 Node.js 提供的命令运行 JS 代码。
- 创建一个
index.js文件,并在其中编写 JS 代码
console.log('hello nodejs');
- 在终端输入命令
node <file name>,运行指定的 js 文件
node index.js
hello nodejs
Node.js API
Node.js 除了使用 ECMAScript 核心语法,还主要使用以下 Node API。
fs,utilhttp,urlconsole,定时器path,......
// 顶级对象
console.log(global);
console.log(globalThis);
// 定时器
setTimeout(() => {
console.log('hello');
}, 0);
在 Node.js 中不能使用 DOM,BOM 及其他浏览器提供的 Web API。如下代码在 Node.js 环境中都会报错。
// BOM
console.log(window);
// DOM
console.log(document);
// Ajax
const xhr = new XMLHttpRequest();
Node.js 模块化
模块化可以将复杂的程序按照一定规范拆分成多个文件,其中拆分出的每一个文件即是一个模块;模块的内部数据是私有的,但是模块可以通过暴露内部数据以提供给外部模块使用。
模块化有以下好处:
- 减少命名冲突,各个模块的同名变量不会冲突
- 高复用性,模块只需引入就可以用于多个外部模块
- 高维护性,对程序的某个模块升级而不会影响其他模块
模块暴露数据的方式有:
module.exportsexports
模块在导入时:
- 通过
require导入指定路径的模块。 - 如果导入的是文件,可以导入 JS 文件或 JSON 文件,文件扩展名可以省略。
- 如果导入的是目录,会检查目录下
package.json文件中main属性的文件是否存在,如果存在则导入此模块;如果没有则检查是否存在index.js或index.json,如果存在则引入此模块,没有则报错。
module.exports
- 使用
module.exports导出定义的模块
function fn() {
console.log('world');
}
module.exports = fn;
- 使用
require导入模块
const my = require('./my');
my();
exports
- 使用
exports导出定义的模块
function hello() {
console.log('world');
}
exports.hello = hello;
- 使用
require导入模块
const my = require('./my');
my.hello();
module.exports/exports区别
在nodejs中使用require引入模块,它实际引入的只是module.exports ,而不是exports;
那为什么exports也能够暴露数据?
虽然module.exports 和 exports都可以用于暴露数据,实际上它们都同时指向一块空的内存空间;
它们之间的关系是:module.exports = exports = {};
因此当通过exports.的方式也就是给对象添加属性或方法,就可以通过module.exports获取;
但是如果直接使用exports =赋值的形式暴露数据,由于更改了引用,此时就不同于module.exports所指向的内存地址,所以当引入模块后也访问不到要暴露的数据,因为暴露的数据来源于module.exports。
通过代码验证module.exports 和 exports指向同一块内存空间:
console.log(module.exports === exports); // true