与浏览器JavaScript的区别

很多前端同学学Node.js时会有困惑:"这跟浏览器里的JavaScript有啥区别?" 说实话,区别挺大的。这节课就给你讲清楚,免得到处踩坑。

一、 运行环境不同

浏览器JavaScript

Node.js JavaScript

二、 全局对象不同

浏览器有

// window - 浏览器窗口对象 window.document // DOM window.alert() // 弹窗 window.location // URL信息

// navigator - 浏览器信息 navigator.userAgent

// history - 浏览历史 history.back()

Node.js有

// global - 全局对象(Node.js独有的) global.console global.setTimeout

// process - 进程对象(Node.js独有的) process.argv // 命令行参数 process.env // 环境变量 process.cwd() // 当前工作目录 process.exit() // 退出进程

// dirname 和 filename(Node.js独有) console.log(dirname); // 当前文件所在目录 console.log(filename); // 当前文件完整路径

三、 模块系统

浏览器(旧版)

以前浏览器里没有模块系统,只能用:

// 1. script标签引入(全局污染)

// 2. 命名空间(容易冲突) var MyApp = {}; MyApp.utils = {};

Node.js - CommonJS

Node.js自带模块系统:

// 导出 module.exports = { name: '小明' };

// 或者 exports.name = '小明';

// 导入 const myModule = require('./myModule');

浏览器(现代)- ES Modules

现在浏览器也支持ES Modules了:

// 导出 export function sayHello() {}

// 导入 import { sayHello } from './module.js';

四、 API差异

DOM操作 - 只有浏览器有

// 这些在Node.js里会报错 document.querySelector('.box') element.innerHTML = 'hello' window.alert('hi')

文件操作 - 只有Node.js有

// 这些在浏览器里会报错 const fs = require('fs'); fs.readFileSync('a.txt') fs.writeFileSync('b.txt', 'content')

console对象 - 两者都有,但有点区别

// 浏览器console console.log('显示在控制台'); console.warn('警告'); console.error('错误'); console.table([{a:1}, {b:2}]); // 浏览器特有

// Node.js console console.log('显示在终端'); console.time('test'); console.timeEnd('test'); console.trace(); // 打印堆栈

五、 异步编程

两边都用异步,但场景不同。

浏览器 - 主要是事件和回调

// setTimeout/setInterval setTimeout(() => {}, 1000);

// AJAX / Fetch fetch('/api/data').then(r => r.json());

// 事件监听 button.addEventListener('click', () => {});

Node.js - 事件 + 回调 + Promise

// 读取文件 const fs = require('fs'); fs.readFile('a.txt', 'utf8', (err, data) => {});

// Promise方式 fs.promises.readFile('a.txt', 'utf8').then(data => {});

// 或者用await const data = await fs.promises.readFile('a.txt', 'utf8');

// EventEmitter const EventEmitter = require('events'); const emitter = new EventEmitter(); emitter.on('event', () => {});

六、 Error处理

浏览器

try { JSON.parse('invalid'); } catch (e) { console.error(e.message); // 浏览器里错误不会导致程序崩溃 }

Node.js

try { JSON.parse('invalid'); } catch (e) { console.error(e.message); }

// 未捕获的异常会中断程序 process.on('uncaughtException', (err) => { console.error('程序要挂了!', err); process.exit(1); });

七、 模块查找规则

浏览器(ES Modules)

import axios from 'axios'; // 找 node_modules/axios // 或者 ../node_modules/axios

必须加路径或者包名,不能相对路径缩写。

Node.js

const axios = require('axios'); // 自动找: // 1. 内置模块(fs, path, http) // 2. node_modules/axios // 3. ../node_modules/axios

更智能,./相对路径也可以。

八、 this的指向

浏览器

// 函数内部this指向window(严格模式除外) function test() { console.log(this); // window }

// 箭头函数this继承外层 const arrow = () => { console.log(this); // window };

Node.js

// 函数内部this是undefined(严格模式) function test() { console.log(this); // undefined }

// 全局this是global对象 global.console.log(global === this); // true

// 箭头函数this不改变 const arrow = () => { console.log(this); // 外层的this };

九、 Buffer和二进制

浏览器

浏览器里用ArrayBuffer和TypedArrays:

const buffer = new ArrayBuffer(8); const view = new Int32Array(buffer);

Node.js

Node.js有额外的Buffer类:

const buf = Buffer.alloc(8); // 分配8字节 buf.write('hello'); console.log(buf.toString());

// 处理文件、图片等二进制数据特别方便

十、 总结对比表

特性 浏览器JS Node.js
运行环境 浏览器 服务器/命令行
DOM ✅ 有 ❌ 没有
文件系统 ❌ 没有 ✅ 有
网络请求 fetch/ajax http/axios
模块系统 ES Modules CommonJS + ESM
全局对象 window global
Buffer
process
__dirname
console 有(更丰富)

十一、 代码复用

虽然有区别,但很多代码是可以共用的:

// 工具函数可以两边跑 function formatDate(date) { return new Date(date).toLocaleDateString(); }

function validateEmail(email) { return /^[^\s@]+@[^\s@]+.[^\s@]+$/.test(email); }

// 业务逻辑可以复用 function calculateTotal(items) { return items.reduce((sum, item) => sum + item.price, 0); }

这些函数既可以在浏览器里用,也可以在Node.js里用。

十二、 学完能做什么

两者结合,就是全栈工程师!

下节课我们继续聊下一个主题,敬请期待!