全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-16 8 分钟 ✍️ juanwangdev

JavaScript 跨平台运行时差异

JavaScript 可运行在浏览器、Node.js、Deno、Bun 等多种运行时环境,各环境存在显著差异。

主流运行时环境

运行时主要场景引擎
Chrome浏览器V8
Firefox浏览器SpiderMonkey
Safari浏览器JavaScriptCore
Node.js服务端V8
Deno服务端V8
Bun服务端JavaScriptCore

全局对象差异

浏览器环境

JavaScript
// 全局对象
window.alert('Hello');
document.getElementById('app');
navigator.userAgent;

// this 指向
console.log(this); // window

Node.js 环境

JavaScript
// 全局对象
global.console.log('Hello');
process.env.NODE_ENV;
Buffer.from('data');

// 模块中的 this
console.log(this); // {}(模块级)

统一访问方式

JavaScript
// 获取全局对象的通用方法
const globalThis =
  typeof window !== 'undefined' ? window :
  typeof global !== 'undefined' ? global :
  typeof self !== 'undefined' ? self :
  this;

// ES2020 标准化
console.log(globalThis);

模块系统差异

CommonJS(Node.js)

JavaScript
// 导出
module.exports = { foo, bar };
// 或
exports.foo = foo;

// 导入
const { foo, bar } = require('./module');

ES Modules(浏览器/现代Node)

JavaScript
// 导出
export const foo = 1;
export default class Foo {}

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

差异对比

特性CommonJSES Modules
加载时机运行时编译时
输出值的拷贝值的引用
this{}undefined
循环依赖可能出问题静态分析

API 差异

DOM API

JavaScript
// 浏览器独有
document.querySelector('.app');
localStorage.setItem('key', 'value');
fetch('/api/data');
alert('Hello');

// Node.js 替代方案
// 使用 jsdom、node-fetch 等库

Node.js 核心 API

JavaScript
// Node.js 独有
const fs = require('fs');
const path = require('path');
const http = require('http');

// 读写文件
fs.readFileSync('./file.txt', 'utf-8');

// 创建服务器
http.createServer((req, res) => {
  res.end('Hello');
}).listen(3000);

共有 API

JavaScript
// 各环境都支持
console.log('Hello');
setTimeout(() => {}, 1000);
setInterval(() => {}, 1000);
Promise.resolve();
Array.isArray([1, 2, 3]);
JSON.stringify({ a: 1 });

异步处理差异

setTimeout 精度

JavaScript
// 浏览器:最小 4ms(HTML5 规范)
setTimeout(() => {}, 0); // 实际约 4ms

// Node.js:可设置 1ms
setTimeout(() => {}, 1);

// Node.js 立即执行
setImmediate(() => {
  // 下一次事件循环立即执行
});

// 浏览器替代方案
requestAnimationFrame(() => {
  // 帧同步回调
});

微任务差异

JavaScript
// 两者一致
Promise.resolve().then(() => {
  console.log('microtask');
});

// Node.js 特有
process.nextTick(() => {
  console.log('nextTick');
  // 优先于其他微任务
});

环境检测

检测浏览器

JavaScript
const isBrowser = typeof window !== 'undefined' &&
                   typeof document !== 'undefined';

检测 Node.js

JavaScript
const isNode = typeof process !== 'undefined' &&
               process.versions &&
               process.versions.node;

检测特定运行时

JavaScript
// Deno
const isDeno = typeof Deno !== 'undefined';

// Bun
const isBun = typeof Bun !== 'undefined';

// Electron
const isElectron = process.versions.electron !== undefined;

跨平台兼容策略

特性检测

JavaScript
// ✅ 检测特性是否存在
if (typeof fetch === 'function') {
  fetch('/api/data');
} else {
  // 使用 polyfill 或替代方案
  xhrRequest('/api/data');
}

// ❌ 不要检测浏览器
if (navigator.userAgent.includes('Chrome')) {
  // 不可靠
}

Polyfill

JavaScript
// 使用 polyfill 填充缺失功能
if (typeof Promise === 'undefined') {
  require('promise-polyfill');
}

if (typeof Object.assign !== 'function') {
  Object.assign = function(target, ...sources) {
    sources.forEach(source => {
      Object.keys(source).forEach(key => {
        target[key] = source[key];
      });
    });
    return target;
  };
}

条件导出(package.json)

JSON
{
  "exports": {
    ".": {
      "browser": "./dist/browser.js",
      "node": "./dist/node.js",
      "default": "./dist/index.js"
    }
  }
}

Buffer vs ArrayBuffer

Node.js Buffer

JavaScript
// Node.js
const buf = Buffer.from('Hello', 'utf-8');
console.log(buf.toString());
console.log(buf.length); // 字节长度

浏览器 ArrayBuffer

JavaScript
// 浏览器
const buffer = new ArrayBuffer(8);
const view = new Uint8Array(buffer);
view[0] = 72; // 'H'

转换方法

JavaScript
// Node.js 15+
const { Buffer } = require('buffer');
const arrayBuffer = buffer.buffer;

// 浏览器环境
const buffer = Buffer.from(arrayBuffer);

要点总结

差异类型浏览器Node.js
全局对象windowglobal
模块系统ES ModulesCommonJS/ESM
文件系统fs 模块
DOM
BufferArrayBufferBuffer
  • 使用 globalThis 获取全局对象
  • 优先使用特性检测而非环境检测
  • 编写库时考虑多种导出格式
  • 注意 setTimeout 的精度差异
  • 使用 package.json exports 做条件导出

📝 发现内容有误?点击此处直接编辑

← 上一篇 JavaScript 编译与解释执行
下一篇 → V8 引擎内部机制
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库