【问题标题】:why is undefined being added to my filtered list?为什么未定义被添加到我的过滤列表中?
【发布时间】:2017-04-25 14:21:26
【问题描述】:

我正在尝试编写一个节点程序,该程序将读取文件目录并过滤掉没有特定文件扩展名的文件。 (这对learnyounode 来说是一个挑战)由于某种原因,它添加到了“未定义”列表中。谁能告诉我为什么?

var fs = require('fs')

var path = process.argv[2];
var ext = process.argv[3];

var fileList = fs.readdir(path, function callback(err, list){
    if (err){
    throw err;
    }
    var filteredList = list.filter(function(fileName){  
    var extRx = new RegExp('\.' + 'md' + '$');
        return extRx.test(fileName);
    });
    console.log(filteredList.forEach(function(val){console.log(val)}));
});

输出:

             ACTUAL                                 EXPECTED                

   "CHANGELOG.md"                      ==    "CHANGELOG.md"                     
   "LICENCE.md"                        ==    "LICENCE.md"                       
   "README.md"                         ==    "README.md"                        
   "undefined"                         !=    ""                                 
   ""                                  !=                                       

【问题讨论】:

  • 需要查看文件名的实际列表才能进行调试。
  • 登录list 并向我们展示结果
  • 旁注:为什么console.log(filteredList.forEach(function(val){console.log(val)})); 而不仅仅是console.log(filteredList)
  • @adeneo 没关系,它应该过滤掉那些,因为它们从不匹配正则表达式。字符串“未定义”也不应该匹配,因此日志记录中一定有问题
  • @Randy - 你是对的,过滤后的列表绝对不可能包含undefined,所以它是外部控制台日志。

标签: javascript node.js filter undefined


【解决方案1】:

这看起来实际上是您的控制台方法的产物。您正在控制台记录过滤列表中的每个元素,然后 控制台记录 forEach 函数的输出。 forEach 函数没有返回值,因此它返回的是您的外部控制台日志然后记录的“未定义”。

考虑将您的控制台日志更改为:

console.log(filteredList);

【讨论】:

  • 不错的收获!再看看这个,不知道我为什么这样做。一定很累。
【解决方案2】:

您没有包含可运行的示例,因此无法告诉您未包含的代码有什么问题,尤其是当您甚至没有包含您要过滤的实际文件列表时。

看这个例子:

var list = [
    "CHANGELOG.md",
    "LICENCE.md",
    "README.md",
    "undefined",
    "",
];
var filteredList = list.filter(function(fileName){
    var extRx = new RegExp('\.' + 'md' + '$');
    return extRx.test(fileName);
});
console.log(filteredList);

这会正确过滤掉您想要的值。 将您的程序更改为包含一个 console.log 语句,以确保您知道正在打印的内容:

console.log(filteredList);

或:

console.log(JSON.stringify(filteredList));

一个建议 - 不要太复杂:

var filteredList = list.filter(function(fileName){
    var extRx = new RegExp('\.' + 'md' + '$');
    return extRx.test(fileName);
});

当你只需要:

var filteredList = list.filter(name => name.match(/\.md$/));

如果你保持简单,调试代码的麻烦会更少。

更新

阅读 cmets 后,我发现 'md' 只是一个占位符,您在实际代码中使用命令行参数。在那种情况下,我会使用 escape-string-regexp 来转义字符串。见:

当您使用escape-string-regexp时:

var escape = require('escape-string-regexp');

你可以这样做:

var extRx = new RegExp('[.]' + escape(ext) + '$');

其中ext 是您作为命令行参数获得的文件扩展名。

这里的[.] 只是我个人在正则表​​达式中写一个点的偏好,我认为它更具可读性,但它不会改变这里的任何行为。转义更重要。

如果您不转义字符串,因为您希望您的用户能够使用自定义正则表达式而不是文字字符串,那么您至少应该将 new RegExp() 调用包装在 try/catch因为它可以在无效的正则表达式语法上抛出异常。

【讨论】:

  • 我为这个例子硬编码了md,但它应该是一个命令行参数,因此是new RegExp对象。你的建议还适用吗?
  • @DavidJ。如果正则表达式的一部分来自命令行参数,那么我将使用escape-string-regexp 使用var escape = require('escape-string-regexp'); var extRx = new RegExp('[.]' + escape(XXX) + '$'); 转义字符串,其中XXX 是命令行参数。 [.] 只是我个人在正则表​​达式中写一个点的偏好,我认为它更具可读性,但它不会改变这里的任何行为。转义更重要。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-18
  • 2023-04-03
  • 2014-08-14
  • 2012-07-28
  • 1970-01-01
  • 2014-02-25
相关资源
最近更新 更多