探索
计算机不会欺骗人,一切按照规则执行,说找不到这个文件,那肯定就是真的找不到,至于为什么找不到,那就是因为我们理解有偏差,我最初理解的'./'是当前执行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 里面我们写这些代码,看看输出是什么:
const path = require('path')
console.log('__dirname:', __dirname)
console.log('__filename:', __filename)
console.log('process.cwd():', process.cwd())
console.log('./:', path.resolve('./'))
在当前目录下也就是nodejs目录运行 node path.js,我们看看输出结果:
__dirname: /Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs
__filename: /Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs/2.path.js
process.cwd(): /Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs
./: /Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs

然后在 项目根目录ES6-lottery 目录下运行 node syntax/nodejs/2.path.js,我们再来看看输出结果:
__dirname: /Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs
__filename: /Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs/2.path.js
process.cwd(): /Users/jawil/Desktop/nodejs/demo/ES6-lottery
./: /Users/jawil/Desktop/nodejs/demo/ES6-lottery

答案显而易见?我们可以通过上面的例子对比,暂时得出表面的结论:
__dirname: 总是返回被执行的 js 所在文件夹的绝对路径
__filename: 总是返回被执行的 js 的绝对路径
process.cwd(): 总是返回运行 node 命令时所在的文件夹的绝对路径
./: 跟 process.cwd() 一样,返回 node 命令时所在的文件夹的绝对路径
但是,我们再来看看这个例子,我们在上面的例子加几句代码,然后:
我们在1.findLargest.js先加这句代码
exports.A = 1;
再来在刚才报错的3.fs.js里面加这两句代码看看:
const test = require('./1.findLargest.js');
console.log(test)
运行node syntax/nodejs/3.fs.js,最后看看结果:

再次疑惑
为什么都是读取./1.findLargest.js文件,一样的路径,为什么require能获取到,而readFile读取不到呢?
于是查了不少资料,看到了一些关于require引入模块的机制,从中学到了不少,也明白了为什么是这样。
我们先了解一下require() 的基本用法:
下面的内容来自require() 源码解读,由阮一峰翻译自《Node使用手册》。

我们从第(2)小条的a部分可以看出:
(2)如果 X 以 "./" 或者 "/" 或者 "../" 开头
  a. 根据 X 所在的父模块,确定 X 的绝对路径。
  b. 将 X 当成文件,依次查找下面文件,只要其中有一个存在,就返回该文件,不再继续执行。
const test = 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() 中使用是跟 __dirname 的效果相同,不会因为启动脚本的目录不一样而改变,在其他情况下跟 process.cwd() 效果相同,是相对于启动脚本所在目录的路径。
总结:
__dirname: 获得当前执行文件所在目录的完整目录名
__filename: 获得当前执行文件的带有完整绝对路径的文件名
process.cwd():获得当前执行node命令时候的文件夹目录名
./: 不使用require时候,./与process.cwd()一样,使用require时候,与__dirname一样
只有在 require() 时才使用相对路径(./, ../)的写法,其他地方一律使用绝对路径,如下:
// 当前目录下
path.dirname(__filename) + '/path.js';
// 相邻目录下
path.resolve(__dirname, '../regx/regx.js');
最后看看改过之后的结果,不会报错找不到文件了,不管在哪里执行这个脚本文件,都不会出错了,防止以后踩坑。

最新文章

  1. 一次sql注入中转
  2. div盒子中子元素(子元素可能是盒子, 图片) 中居中的三种方法
  3. git clone --early EOF
  4. Js练习题之字符串转驼峰
  5. 非root模式下安装mysql php小记
  6. SQL语句查询结果额外加入一列序号自己主动添加
  7. 百度Echarts使用心得
  8. android File文件的读写操作
  9. Tsinsen-1487:分配游戏【树状数组】
  10. 利用ssh反向代理以及autossh实现从外网连接内网服务器
  11. linux系统下安装配置解压版的MySQL数据库
  12. alias 命令详解
  13. NOIP 2018 大翻车记
  14. Docker最全教程——从理论到实战(三)
  15. 1个多商户、多平台版 微信小程序(多商户、多平台版),影城行业、影业连锁 多商户、多平台版微信小程序。(基于多平台版,支持在业务上 可给 每个单独影城 分发定制单独的小程序版本)
  16. Node辅助工具NPM&REPL
  17. 【ZZ】堆和堆的应用:堆排序和优先队列
  18. django具体操作(七)
  19. 自定义vue全局组件use使用
  20. RabbitMQ和Kafka对比以及场景使用说明

热门文章

  1. mac上的webStorm上配置gitHub
  2. 【BZOJ4711】小奇挖矿 树形DP
  3. iOS UITextView 展示html
  4. SpringBoot专题1----springboot与mybatis的完美融合
  5. npm的本地模式与全局模式
  6. ffmpeg命令
  7. win8 内置管理员账号既能使用metro应用又能使用默认共享
  8. Python--(并发编程之线程Part2)
  9. 【Linux】Ubuntu下录屏&&制作GIF
  10. hibernate自动建表之engine设置