使用Array.prototype.filter()结合includes校验数组时的数组变量传参异常问题
嘿,我来帮你拆解这个问题的核心,其实是对String.prototype.includes()的参数理解偏差,加上JavaScript逗号运算符的小陷阱在搞鬼~
为什么第一段代码能得到预期结果?
你写的word.includes('e', 'i'),其实includes的第二个参数是搜索的起始位置(必须是数字),不是第二个要匹配的字符。当你传字符串'i'时,它会被隐式转换成数字,结果是NaN,而includes遇到起始位置为NaN时,会默认用0。所以这段代码实际等价于:
word.includes('e', 0)
也就是找所有包含字符'e'的单词,刚好你预期里的四个单词都包含'e',所以运行结果和预期一致——但这其实是个巧合,你以为是同时匹配'e'和'i',但实际只是匹配'e'而已。
为什么传数组test会得到空数组?
includes的第一个参数要求是字符串类型,当你传入数组['e','i']时,JavaScript会自动把数组转换成字符串,也就是'e,i'。你的words数组里没有任何一个单词包含子串'e,i',自然就返回空数组[]了。
为什么test[0,1]又能得到预期结果?
这里用到了JavaScript里的逗号运算符:逗号运算符会依次计算所有表达式,然后返回最后一个表达式的值。所以test[0,1]等价于test[1],也就是取数组里的第二个元素'i'?不过这里有点小矛盾——如果匹配'i'的话,'limit'也包含'i',应该会出现在结果里。可能你这里的描述有小误差?但不管怎样,test[0,1]的本质是逗号运算符在起作用,它返回的是1,所以取的是test[1]。
正确实现:匹配多个字符中的任意一个/全部
如果你想实现“单词包含'e'或'i'”的逻辑,正确写法有两种:
方法1:用逻辑或(适合少量字符)
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present']; const test = ['e', 'i']; const result = words.filter(word => word.includes(test[0]) || word.includes(test[1])); console.log(result); // 输出:["limit", "elite", "exuberant", "destruction", "present"]
方法2:用正则表达式(适合多字符场景)
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present']; const test = ['e', 'i']; const regex = new RegExp(test.join('|')); const result = words.filter(word => regex.test(word)); console.log(result); // 输出:["limit", "elite", "exuberant", "destruction", "present"]
如果你的需求是同时包含'e'和'i'(和你最开始的预期结果一致),那用逻辑与即可:
const result = words.filter(word => word.includes(test[0]) && word.includes(test[1])); console.log(result); // 输出:["elite", "exuberant", "destruction", "present"]
内容的提问来源于stack exchange,提问作者Anthony LoPrimo

