可通过全局对象、执行上下文和模块特征区分JavaScript运行环境:浏览器控制台中window和console存在但import.meta未定义、document.currentScript为null;HTML script标签中document.currentScript非null且import.meta未定义;ES模块中import.meta为对象且this为undefined;Node.js中process存在,REPL中module.filename为'<repl>'或undefined。

可以通过检查全局对象、执行上下文和模块环境特征来区分当前 JavaScript 运行环境。核心思路是:不同环境暴露的全局变量、顶层 this 指向、模块相关属性(如 import.meta)、以及可调用接口(如 console 或 require)存在明显差异。
检测是否在浏览器控制台(DevTools Console)中运行
控制台环境不具备标准模块上下文,但有完整的 window 和 console,且顶层 this 通常指向 window;关键区别在于它**不支持 import.meta**(会报错),也**没有 module 对象**,同时 document.currentScript 为 null(因非 script 标签执行)。可结合以下判断:
-
typeof window !== 'undefined' && typeof document !== 'undefined'→ 排除 Node.js -
typeof import.meta === 'undefined'→ 控制台不支持import.meta -
document.currentScript === null→ 不在<script>标签内执行 -
typeof module === 'undefined'→ 排除 CommonJS 模块
检测是否在 HTML 的 <script> 标签中运行
普通内联或外链 script 标签(非模块)中,document.currentScript 指向当前执行的 script 元素,且 import.meta 未定义(除非显式声明 type="module")。注意:type="module" 的 script 属于模块环境,需单独判断。
-
document.currentScript !== null→ 明确处于某个<script>标签执行流中 -
typeof import.meta === 'undefined'→ 非 ES 模块脚本 -
typeof module === 'undefined'→ 非 CommonJS
检测是否在 ES 模块(<script type="module"> 或 .mjs 文件)中运行
ES 模块环境最可靠的标识是 import.meta 存在且为对象,并且顶层 this 是 undefined(严格模式下)。在浏览器中,模块 script 的 document.currentScript 仍有效,但 Node.js 的 .mjs 模块中该属性不可用。
-
import.meta && typeof import.meta === 'object'→ 强信号(浏览器模块 / Node.js .mjs) -
typeof this === 'undefined'→ 模块顶层严格模式特性(非全局作用域) -
typeof module === 'undefined'→ 区分于 CommonJS
检测是否在 Node.js REPL 或 CommonJS 模块中运行
Node.js 环境可通过 process 判断,REPL 与普通 CommonJS 脚本的区别在于 require.main === module 为 false(REPL 中无主模块),且 module.parent 为 null。同时,REPL 中 globalThis.module 存在但 module.filename 为 undefined 或 '<repl>'。
-
typeof process !== 'undefined' && process.versions && process.versions.node→ 确认 Node.js -
typeof require !== 'undefined' && typeof module !== 'undefined'→ CommonJS 特征 -
!module.filename || module.filename === '<repl>'→ 高概率为 REPL -
module.parent === null && require.main !== module→ REPL 典型表现
实际使用时建议组合多个条件,避免单点误判。例如浏览器模块中 import.meta 存在,但 process 不存在;Node.js REPL 中 module.filename 为 '<repl>',而普通 .cjs 脚本中该值为真实路径。不复杂但容易忽略细节。

















