Nodeschool learnyounode Filter LS练习报错:Cannot read property 'toString' of undefined
问题根源分析与修复方案
你的代码出现报错的核心问题在于循环条件的错误,下面一步步拆解原因:
1. 为什么会出现TypeError: Cannot read property 'toString' of undefined?
fs.readdir返回的list是一个包含文件名的数组,数组里的元素都是字符串,而且数组末尾根本不存在'\0'(这是C语言里的字符串结束标记,Node.js的数组不会用这个)。当你的循环变量i增长到等于数组长度时,list[i]就会变成undefined,这时候你调用list[i].toString(),自然就会触发“无法读取undefined的toString属性”的错误。
2. 为什么去掉toString()会报'Path must be a string'?
本质上还是同一个问题:当循环到i >= list.length时,list[i]是undefined,你把undefined传给path.extname(),而这个方法要求参数必须是字符串类型,所以就抛出了这个错误。其实list里的每个元素本来就是字符串,你完全不需要额外调用toString()来转换。
修复后的代码
把循环条件改成基于数组长度判断,就可以解决问题:
var fs = require('fs'); var path = require('path'); fs.readdir(process.argv[2], function (err, list) { if(err) return console.log(err); for(var i = 0; i < list.length; i++) { const fileName = list[i]; if('.' + process.argv[3] === path.extname(fileName)) { console.log(fileName); } } });
额外优化(可选)
如果你不想用forEach,也可以用数组的filter方法来简化逻辑(最终还是用for循环输出也可以):
var fs = require('fs'); var path = require('path'); fs.readdir(process.argv[2], function (err, list) { if(err) return console.log(err); const targetExt = '.' + process.argv[3]; const matchingFiles = list.filter(file => path.extname(file) === targetExt); // 不用forEach的话,继续用for循环输出 for(let i = 0; i < matchingFiles.length; i++) { console.log(matchingFiles[i]); } });
内容的提问来源于stack exchange,提问作者Dhairya Khale
相关产品推荐
相关产品推荐

