大家好,我是哈默。今天我们先通过对比的方式了解一下 __dirname
的作用,然后从原理角度,帮助大家加深理解。
目录结构
└─code
└─folder-1
└─folder-1-1
└─index.js
假如在这样的一个目录结构中,我们采用 2 种方法,来尝试获取 index.js
的绝对路径。
使用相对路径
// index.js
const path = require("path");
console.log(path.resolve("./"));
console.log(path.resolve(__dirname));
结果会发现,如果我们使用 web 开发时常用的 ./
这种相对路径的写法,会得到不同的结果。
在 第一级 code 目录
执行代码,得到的结果:
// index.js
const path = require("path");
console.log(path.resolve("./")); // code的父文件夹/code
// 备注:上面的console.log完整结果为:/Users/tuomatuo/Documents/code/shuibuzhuo-blog/docs/node/__dirname的作用/code
// 这里为了阅读方便,将 `/Users/tuomatuo/Documents/code/shuibuzhuo-blog/docs/node/__dirname的作用` 称为 `code的父文件夹`,下面也是一样的意思
在 第二级 folder-1 目录
执行代码,得到的结果:
// index.js
const path = require("path");
console.log(path.resolve("./")); // code的父文件夹/code/folder-1
在 第三级 folder-1-1 目录
执行代码,得到的结果:
// index.js
const path = require("path");
console.log(path.resolve("./")); // code的父文件夹/code/folder-1/folder-1-1
可以发现,它会因为我们 命令执行时,所处的文件夹位置不同,而得到一个动态的变化的结果。
使用__dirname
但是,当我们使用 __dirname
的话,则始终获取到的就是执行的 index.js
文件所在的文件夹的绝对路径。
在 第一级 code 目录
执行代码,得到的结果:
// index.js
const path = require("path");
console.log(path.resolve(__dirname)); // code的父文件夹/code/folder-1/folder-1-1
在 第二级 folder-1 目录
执行代码,得到的结果:
// index.js
const path = require("path");
console.log(path.resolve(__dirname)); // code的父文件夹/code/folder-1/folder-1-1
在 第三级 folder-1-1 目录
执行代码,得到的结果:
// index.js
const path = require("path");
console.log(path.resolve(__dirname)); // code的父文件夹/code/folder-1/folder-1-1
可以看到,无论我们 在命令执行时,所处的文件夹位置在哪里,我们得到的结果都是执行的 index.js
文件所在的文件夹的绝对路径。
另一个内置变量__filename
除了 __dirname
之外,node 还给我们提供了另一个内置的变量:__filename
,用来获取当前执行的文件名。
// index.js
const path = require("path");
console.log(__filename); // code的父文件夹/code/folder-1/folder-1-1/index.js
为什么能直接访问?
我们再深入一点,来看一下为什么我们能直接访问到 __dirname
和 __filename
呢?
我们可以把我们写的每一个 js 文件,看作是一个模块。
那么在 node 执行我们模块代码的时候,实际上会以下面这种方式来执行:
(function (exports, require, module, __filename, __dirname) {
// 模块源码
});
这样一来,我们写的模块源码就可以访问到参数里面的 __filename
和 __dirname
。
而 __filename
和 __dirname
又是事先定义好的,直接作为参数传入即可。
总结
在 node 中,我们有 2 个全局的内置变量,__dirname
和 __filename
。
__dirname
可以用来获取执行的文件所在的文件夹的路径。
__filename
可以用来获取当前执行的文件名。