原文收录在我的GitHub博客(https://github.com/jawil/blog),喜欢可以关注最新动态,一起多交流多学习,共同进步,以学习者的身份写博客,记录点点滴滴。最近在研究Node.js中的fs模块时,遇到一个比较奇怪的现象。踩坑的时候,只是读了当前目录下的一个文件,死活读不出来。对它不是很熟悉,也没有系统研究过,所以今天踩了这个坑,把踩坑的过程记录下来,防止踩坑和大家一起踩坑将来。先说一下当时的情况吧:我纳闷了半天。我显然在当前目录中读取了1.findLargest.js。为什么提示找不到这个文件?跑了好几次都找不到1.findLargest.js。文档。后来发现文件不是从当前目录运行的。从图中可以看出,当前目录是/Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs,我运行这个脚本的目录是/Users/jawil/Desktop/nodejs/demo/ES6-彩票;这就是问题所在。但是为什么脚本运行的位置也会影响这个路径呢,往下看。探索计算机不会骗人。一切都按照规则执行。如果说找不到这个文件,那一定是真的找不到。至于为什么找不到,是因为我们的理解有偏差。我对'./'的初步理解是当前正在执行的js文件所在文件夹的绝对路径,但是对Node.js的理解不是这样的,我们慢慢往下看。Node.js中的文件路径大概有__dirname、__filename、process.cwd()、./或../,前三个是绝对路径,为了比较,./和../我们通过path.resolve('./')转换为绝对路径。简单说一下这几个路径的含义:__dirname:获取当前执行文件所在目录的完整目录名__filename:获取当前执行文件的完整绝对路径的文件名process.cwd():获取当前执行的node命令当时文件夹的目录名./:文件所在目录我们看一下我电脑当前的目录结构:syntax/-nodejs/-1.findLargest.js-2。path.js-3.fs.js-regs-regx.js-test.txt在path.js中我们编写这段代码并查看输出是什么:constpath=require('path')console.log('__dirname:',__dirname)console.log('__filename:',__filename)console.log('process.cwd():',process.cwd())console.log('./:',path.resolve('./'))是当前目录下的nodejs目录运行nodepath.js,我们看输出:__dirname:/Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs__filename:/Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs/2.path.jsprocess.cwd():/Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs./:/Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs然后在项目根目录的ES6-lottery目录下运行nodesyntax/nodejs/2.path.js,我们再看一下输出:__dirname:/Users/jawil/桌面/nodejs/demo/ES6-lottery/syntax/nodejs__filename:/Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs/2.path.jsprocess.cwd():/Users/jawil/Desktop/nodejs/demo/ES6-lottery./:/Users/jawil/Desktop/nodejs/demo/ES6-lottery答案显而易见?我们可以对比上面的例子,得出一个粗浅的结论:__dirname:总是返回执行的js所在文件夹的绝对路径__filename:总是返回执行的js的绝对路径process.cwd():total返回绝对路径运行节点命令的文件夹的名称。/:同process.cwd(),返回node命令所在文件夹的绝对路径。但是,让我们再看看这个例子。在上面的例子中,我们添加了几行代码,然后:我们首先在1.findLargest.js中添加这行代码exports.A=1;然后在刚才报错的3.fs.js中加入这两行代码:consttest=require('./1.findLargest.js');console.log(test)runnodesyntax/nodejs/3.fs.js,最后看结果:再次疑惑为什么读取./1.findLargest.js文件,同样的Path,为什么可以requireget,但是readFile无法读取它?于是查了很多资料,看到了一些require导入模块的机制,从中学到了很多东西,明白了为什么会这样。先来了解一下require()的基本用法:以下内容来自require()源码解读,译自《Node使用手册》byRuanYifeng。我们从(2)小节的a部分可以看出:(2)如果X以“./”或“/”或“../”开头, a。根据X所在的父模块,确定X为.zip文件的绝对路径。 b。把X当作一个文件,依次查找后面的文件,只要有一个存在,就返回该文件,不再继续执行。consttest=require('./1.findLargest.js')根据上面的规则翻译:根据1.findLargest.js所在的父模块,确定1.findLargest.js的绝对路径为/Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs,搜索细节这里不再赘述。首先,把1.findLargest.js当做一个文件,在当前目录依次查找1.findLargest.js,找到就返回该文件,不再继续执行。按照require的基本规则,出现上面的情况也就不足为奇了。require的更多机制和源码解读,请移步:require()源码解读。那么关于./的正确结论是:在require()中使用与__dirname效果相同,不会因为启动脚本的目录不同而改变。在其他情况下,它与process.cwd()具有相同的效果,它是相对于Path到启动脚本所在目录的。总结:__dirname:获取当前执行文件所在目录的完整目录名__filename:获取当前执行文件带有完整绝对路径的文件名process.cwd():获取node命令时的文件夹目录名当前正在执行./:不使用require时,./等同于process.cwd()。使用require时,它??与__dirname相同。require()中只使用相对路径(./,../),其他地方使用绝对路径,如下://当前目录下的path.dirname(__filename)+'/path.js';//相邻目录中的path.resolve(__dirname,'../regx/regx.js');最后看看修改后的结果,不会报错,找不到文件。无论脚本文件执行到哪里,都不会出错,以防日后落井下石。
