Node.js 入门

内容纲要

查看「JavaScript 和它的朋友们专题」获取更多相关内容


简介

从浏览器环境到操作系统舞台

在过去,JavaScript 一直被认为是一种仅限于浏览器的语言,主要用于制作网页上的滚动动画和交互效果。然而,随着 Ryan Dahl 的出现,这一切发生了改变。

2009 年,Ryan Dahl 不甘心 JavaScript 只被束缚在浏览器中,他基于当时 Chrome 浏览器的 JavaScript 引擎 V8 创建了 Node.js,赋予了 JavaScript 运行在操作系统层面的能力。

这标志着 JavaScript 迈出了关键的一步,从浏览器环境走向了更广阔的舞台。Node.js 的出现,让 JavaScript 不再局限于网页制作,摇身一变成为了一门功能强大的后端开发语言。

与传统语言的异同

与 Python、Ruby 和 PHP 等传统操作系统语言相比,Node.js 拥有以下几点关键差异:

  • 运行环境: 传统语言直接运行在操作系统上,而 Node.js 则通过自己的运行环境来执行 JavaScript 代码;
  • 输出方式: 传统语言的程序通常通过图形界面呈现结果,而 Node.js 主要通过命令行界面输出文本信息;
  • 核心功能: 传统语言擅长处理系统任务和文件操作,而 Node.js 则专注于网络通信和事件驱动编程;

尽管存在差异,Node.js 的核心仍然是 JavaScript 语言本身。如果你已经掌握了 JavaScript,那么学习 Node.js 将会非常轻松,因为你只需要熟悉一些环境相关的特性和新的 API 即可。

Node.js 的发展之路

自诞生以来,Node.js 经历了快速发展和起伏跌宕。曾经一度陷入停滞,甚至催生了短命的替代方案 IO.js。然而,社区的质疑和竞争反而激发了 Node.js 团队的斗志,他们积极改进,版本更新不断加速,并逐渐赢回了开发者的信任。

如今,Node.js 已成为最流行的后端运行环境之一,被广泛应用于服务器开发、代理服务、构建工具等诸多领域。如果你想涉足 Web 开发,那么掌握 Node.js 必不可少,因为它几乎无所不在,从服务器端到前端框架构建,其身影无处不在。

Node.js 的特点

非阻塞 I/O vs. 传统的同步执行:

  • 传统语言通常采用同步执行,一个任务完成后才能开始下一个,就像排队一样,效率会受到限制;
  • Node.js 使用非阻塞 I/O,可以同时启动多个任务,并使用事件循环机制异步处理它们的返回结果;

想象一下,你在餐厅点餐,服务员可以同时接多个订单,而不用一个个排队等待上菜。这就是非阻塞 I/O 的核心思想。

事件循环的巧妙之处:

  • 事件循环就像一个勤奋的管家,不断检查待办事项列表,并按照一定顺序逐个执行任务。
  • 当一个任务完成后,它会触发相应的回调函数,就像服务员把菜端到你面前一样,告诉你任务已经完成。

这样一来,多个任务可以交替执行,不会因为等待某个任务而浪费时间,提高了整体效率。

Node.js 和 JavaScript 的密切关系:

  • Node.js 是 JavaScript 的运行环境,就像舞台一样,让 JavaScript 代码可以在服务器上运行。
  • 如果你已经掌握了 JavaScript,那么学习 Node.js 就相当于换了个舞台,学习一些新的道具和灯光的使用方法。
  • 核心语法和函数都是一样的,你只需要熟悉 Node.js 特有的 API 和概念,比如文件操作、网络通信等,就能轻松上手。

Node.js 的并发优势:

  • 非阻塞 I/O 和事件循环让 Node.js 非常擅长处理并发请求,就像餐厅能同时接待多位客人一样。
  • 因此,Node.js 非常适合开发服务器端应用,比如聊天室、在线游戏、API 等,能够高效地处理大量并发请求。

安装 Node.js

安装 Node.js 的最直接方法是前往 Node.js 的官方网站下载对应你所用系统的安装包,但个人更推荐使用 nvm。

nvm

nvm(Node Version Manager)是一个符合 POSIX 标准的 bash 脚本,用于管理多个活动的 Node.js 版本。

有时候你会面临需要不同版本 Node.js 的项目,这时候 nvm 就起到了极大的帮助

你在可以在 macOS、Linux、Windows 上的 WSL2 上使用以下命令安装:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash

安装完成后针对你所使用的 shell 编辑其配置文件,如我使用的 shell 为 zsh,那么:

vim ~/.zshrc

除了 zsh,其他的一些常见 shell 的路径及文件名通常为:

  • bash: ~/.bashrc
  • zsh: ~/.zshrc
  • ksh: ~/.profile

如果你不知道自己所使用的 shell 可以使用命令 echo $SHELL,通过其返回结果如 /bin/bash 你就知道这是使用的 bash,一般来说大多数 Linux 和旧版本的 macOS 都是使用的 bash

在配置文件底部添加如下内容:

export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm

然后使用命令另其生效:

# 如果你使用的是其他 shell 则如下示例的 ~/.zshrc 也要相应修改
source ~/.zshrc

查看 nvm 版本:

nvm -v
0.38.0

能看到版本号表示安装及配置成功了,然后使用 nvm 安装 Node.js:

# 列出可安装的 Node.js 版本
nvm ls-remote

# 安装
nvm install --lts # 安装 LTS 版 Node.js
nvm install node # 安装最新版 Node.js
nvm install 20.10.0 # 安装指定版本  Node.js

# 使用指定版本
nvm use node # 使用安装好的最新版
nvm use --lts # 使用安装好的 LTS 版

# 查看安装路径
nvm which 20.0.0

# 卸载
nvm uninstall 20.0.0 # 卸载指定版本

运行

你可以在终端运行命令 node,这样就进入了 Node.js 的交互式解释器,也就是 REPL(Read Eval Print Loop)。如果使用过 Python 等其他语言应该会感到熟悉,不然也可能觉得它像浏览器里的 Console

可以动手试试它都可以执行哪些内容,哪些是浏览器能执行但是在 Node.js 中不能执行的

但一般来说并不会直接使用 Node.js REPL

如果不知道在终端中从 REPL 中退出来,可以输入 .exit 或按 Ctrl + D

编写一个最简单的 JavaScript 代码:

console.log('hi')

并存成 index.js 文件,然后使用命令:

node index.js

这就是一个简单的如何在浏览器以外的环境通过 Node.js 运行一段代码的方法了

浏览器 vs Node.js

全局对象

  • 浏览器中,几乎所有东西都附加在 window 对象上,因此你可以直接使用 alert 函数;
  • Node.js 中没有 window 对象,其全局对象类似于浏览器中的 global 对象,但很少直接使用;
// 在浏览器中
console.log(window);

// 在 Node.js 中
console.log(global);

通过条件判断(如检查 window 是否存在)可以编写兼容两环境的 JavaScript 代码。

许多熟悉的函数(例如 clearTimeoutsetTimeout)在两者中都存在,但使用方式可能有所不同;

操作 DOM

  • 浏览器拥有 DOM (Document Object Model),用于操作网页元素;
  • Node.js 没有任何 DOM,因为它运行在服务器端,不负责渲染网页;

模块
浏览器和 Node.js 都支持模块,但定义方式不同:

  • 浏览器使用 <script type="module"> 标签导入模块
    可以使用脚本标签在浏览器中导入模块,将 type 属性设置为 module 并将 src 属性设置为模块文件的路径:

    <script type="module" src="./module.js"></script>

    可以从名为 module.js 的模块导入 sayHello 函数,并在主 JavaScript 文件中使用它:

    import { sayHello } from './module.js';
    sayHello();
  • Node.js 则使用 importexport 语句。
    import { module } from './module.js';

Node.js REPL(Read-Eval-Print-Loop)

  • 浏览器和 Node.js 都提供 REPL 环境,用于直接执行 JavaScript 代码;
  • Node.js 的 REPL 适合快速测试代码片段,但不适合构建应用程序;

服务器与网站
Node.js 主要用于服务器端应用程序,而浏览器则用于网站


最后,如果感兴趣,可以看看文章开头的「Node.js:纪录片 | 一个起源故事