六维教程

Node.js 第一个程序

上一篇 Node.js 是什么 说清了 Node.js 的来龙去脉,这篇开始动手写代码。你会学到运行 JS 的两种方式,认识 globalconsoleprocess 这三个 Node.js 环境的核心对象。跑通这几个例子,你就正式踏入 Node.js 世界了。

运行 JS 的两种方式

方式一,REPL 交互式环境

REPL 是 Read-Eval-Print-Loop 的缩写,输入一行立即执行一行。终端里直接敲 node 回车就进入这个环境。

node
# 进入 REPL,提示符变成 >
> 1 + 2
3
> const name = "小明"
undefined
> name
'小明'
> .exit

输入 1 + 2 立刻返回 3,变量也能记住。适合随手验证语法,退出用 .exit 或按两次 Ctrl+C。

方式二,运行 JS 文件

正式写程序都放在 .js 文件里,用 node 文件名.js 运行。

node hello.js

文件方式才是实际开发的主力,REPL 只用来临时测试。两种方式都走同一套 V8 引擎,语法完全一致。

global 对象

global 对应浏览器的 window

浏览器里 window 是全局对象,Node.js 里对应的是 globalconsolesetTimeout 这些内置对象都挂在它上面。

console.log(global.console === console);   // true,同一个对象
console.log(global.process === process);   // true,同一个对象
对比项 浏览器 window Node.js global
document 没有
location 没有
process 没有
__dirname 没有

globalThis 统一访问

为了写代码时不区分环境,ES2020 引入了 globalThis,无论在浏览器还是 Node.js 里都指向当前环境的全局对象。

// 在浏览器里 globalThis 就是 window,在 Node.js 里就是 global
console.log(globalThis === global);   // Node.js 中输出 true

全局对象可以直接用名字访问,console.log(global)console.log(globalThis) 结果相同,日常写代码加不加 global. 前缀都行。

浏览器有而 Node.js 没有的

浏览器里随手可用的 documentwindow,在 Node.js 里都不存在。用 typeof 验证最直观,它不会因为变量不存在而报错。

// typeof 不存在的变量返回 "undefined",不会抛错
console.log(typeof document);   // undefined
console.log(typeof window);     // undefined

如果直接写 document.title,Node.js 会报 document is not defined。原因很简单,服务器环境里没有页面这个概念,自然没有文档对象。

console 对象

console.log 输出到标准输出(stdout),运行程序时直接显示在终端。它支持 %s%d 这类格式化占位符。

const name = "小明";
const age = 18;

console.log("我叫 %s,今年 %d 岁", name, age);
// 我叫 小明,今年 18 岁

console.error 输出到标准错误(stderr),终端里照样能看见,但语义上表示出错信息,日志系统会区分两者。

console.error("这里出错了");

调试时还有 console.table,把对象数组打印成表格,看数据比 console.log 清楚得多。

process 对象

process 是 Node.js 的进程对象,程序运行时代表当前这个进程,信息量很大。

process.argv 命令行参数

node greet.js 小明
// greet.js
console.log(process.argv);
// 输出。
// [ 'C:\\node\\node.exe', 'C:\\projects\\greet.js', '小明' ]

前两个位置是固定的,第一个是 node 可执行文件的路径,第二个是当前文件路径,从第三个开始才是你传的参数。取值要写 process.argv[2] 起步。

process.env 环境变量

process.env 是包含所有环境变量的对象,按操作系统不同内容也不一样。

console.log(process.env.PATH);        // 系统路径
console.log(process.env.NODE_ENV);    // 开发中常用来区分环境

其他常用属性

console.log(process.platform);   // win32 / darwin / linux,判断操作系统
console.log(process.cwd());      // 当前工作目录,程序从哪个目录启动

process.exit(1);                 // 退出进程,0 表示正常,非 0 表示异常
// 后面的代码不会执行

process.cwd() 返回的是启动目录,不等于文件所在目录,新手经常在这里踩坑。

实践

hello.js

新建一个 hello.js

// hello.js
console.log("Hello Node.js");

运行。

node hello.js
# 输出 Hello Node.js

greet.js 接收命令行参数

再写一个能打招呼的程序。

// greet.js
const args = process.argv.slice(2);   // 丢掉前两个固定项,只留用户参数

if (args.length === 0) {
  console.error("请提供名字,例如 node greet.js 小明");
  process.exit(1);                    // 参数缺失,以错误码退出
}

console.log("你好,%s!欢迎学习 Node.js", args[0]);
node greet.js 小明
# 你好,小明!欢迎学习 Node.js

node greet.js
# 请提供名字,例如 node greet.js 小明

常见坑

  • 在 REPL 里写的变量,退出后全部清空,想保留代码就存成文件。
  • process.argv 的参数从第 3 个(下标 2)开始取,前两个是 node 路径和文件路径。
  • 直接写 documentwindow 会报未定义,Node.js 里没有浏览器对象,用 typeof 检查最安全。
  • process.cwd() 是启动目录不是文件目录,在别的目录启动程序时结果会不一样。
  • console.error 也是输出到终端的,肉眼分辨不出差别,但脚本管道和日志系统会区分 stdout 与 stderr。

运行程序的两种方式和这三个核心对象都摸清了,下一步学怎么把代码拆成多个文件,见 Node.js 模块系统

上一篇
Node.js 环境搭建
下一篇
Node.js 模块系统