站长资讯网
最全最丰富的资讯网站

浅析nodejs中的__dirname和__filename变量

本篇文章带大家了解一下node中你不知道的__dirname和__filename变量,有一定的参考价值,希望对大家有所帮助!

浅析nodejs中的__dirname和__filename变量

1.问题背景

写这篇文章的背景在于今天遇到一个神奇的报错,一起来看下

// index.js console.log(__filename); // 执行 node index.js // ReferenceError: __filename is not defined in ES module scope

在node环境访问全局变量__filename居然报错,什么原因呢??于是开始了一路的探索,最终找到问题的根源。

2. node模块机制

我们知道早期node.js的模块标准采用commonjs模块规范,然而在nodejs版本v13.2.0中,开始支持ES Modules模块规范,我们可以有以下几种方式在node中使用ES Modules模块

  • 将文件后缀命名为.mjs
  • package.json 新增 "type": "module"字段

当我们在node中使用ES Modules贵方,以下全局对象和变量将不可用

  • require
  • module.exports
  • exports
  • __filename
  • __dirname
  • NODE_PATH

3. 为什么采用commonjs模块化可以使用__filename和__dirname?

这个问题,主要归结于commonjs模块下nodejs的运行机制,很多人可能认为__filename就是node环境中的全局变量,当出现这个问题的时候,我们才意识到,这两个不是Node中真正的全局变量。

看一段简单的js代码

(function(){     console.log(arguments) // [1,2,3] })(1,2,3)

arguments在函数内部可以拿到调用函数时传入的参数。

我们在node commonjs模块中执行以下代码

// index.js console.log(arguments); [Arguments] {   '0': {},   '1': [Function: require] {     resolve: [Function: resolve] { paths: [Function: paths] },     main: Module {       id: '.',       path: 'E:\nodeProjectStorehouse\nodeStudyFromBook',       exports: {},       filename: 'E:\nodeProjectStorehouse\nodeStudyFromBook\cc.cjs',       loaded: false,       children: [],       paths: [Array]     },     extensions: [Object: null prototype] {       '.js': [Function (anonymous)],       '.json': [Function (anonymous)],       '.node': [Function (anonymous)]     },     cache: [Object: null prototype] {       'E:\nodeProjectStorehouse\nodeStudyFromBook\cc.cjs': [Module]     }   },   '2': Module {     id: '.',     path: 'E:\nodeProjectStorehouse\nodeStudyFromBook',     exports: {},     filename: 'E:\nodeProjectStorehouse\nodeStudyFromBook\cc.cjs',     loaded: false,     children: [],     paths: [       'E:\nodeProjectStorehouse\nodeStudyFromBook\node_modules',       'E:\nodeProjectStorehouse\node_modules',       'E:\node_modules'     ]   },   '3': 'E:\nodeProjectStorehouse\nodeStudyFromBook\cc.cjs',   '4': 'E:\nodeProjectStorehouse\nodeStudyFromBook'

我们可以看到,arguments有5个参数,这5个参数就是exports, require, module, __filename, __dirname

到这里我们就清楚的知道,__filename不是全局变量,而是外层传入的参数而已

既然这样,我们在ES Modules模块下,访问arguments看下结果是什么?

// index.js ES modules console.log(arguments); // ReferenceError: arguments is not defined

4. ES Modules下如何使用__filename和__dirname?

node官方文档建议使用import.meta.url变相的提供

// import.meta.url 返回模块的绝对的 `file:` URL。 // url模块中fileURLToPath()函数,返回完全解析的特定于平台的 Node.js 文件路径 // path模块中dirname()函数,返回路径的目录路径 import { fileURLToPath } from 'url'; import { dirname } from 'path'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename);

赞(0)
分享到: 更多 (0)