【面试】你真的理解 filter 吗?

81 阅读2分钟

今天做了 2 道面试题,先记录第一题,关于 Array 的方法 filter 的用法。

题目:不改变数组 oldArr,根据要删除的索引列表 delIdxList,生成新的数组 newArr。数组元素可能重复。

let oldArr = [1,3,4,6]
let newArr = []
let delIdxList = [1, 3]

// TODO

console.log(oldArr, newArr)

一开始,是这样的:

newArr = oldArr.filter((item, index) => {
  if (!delIdxList.includes(index)) {
    return item
  }
})

但是面试官提示我这样会有问题,如果 let oldArr = [1,3,4,6, false, undefined],结果就不对了。

在面试那个环境下,我竟然没想出怎么解决。关注点一直在返回的 item 怎么处理,怎么判断呢?然后发现处理不了,return false 就没了,你没办法返回 false 这个值。

我想这时就要看 filter 是怎么实现的才好。期间我一直在想一种写法,但是想不到这里怎么应用。最后面试官说了改法。

看 filter 的说明:

image.png

newArr = oldArr.filter((item, index) => !delIdxList.includes(index))

这样就好了。

MDN 中对传入 filter 的函数的解释:

Function is a predicate, to test each element of the array. Return a value that coerces to true to keep the element, or to false otherwise.

predicate,谓词。

百度百科对谓词的解释:

谓词:在计算机语言的环境下,谓词是指条件表达式的求值返回真或假的过程。

  1. 这个函数谓词用于测试数组的每个元素。
  2. 每一次判断,返回一个值为 true 或者 false,如果是 true,就保留这个元素,如果是 false,不保留这个元素。

coerces 是强迫、强制的意思,但是这里有点不好理解,后来我又查到type coercion是类型转换的意思: JavaScript type coercion explained

应该是可以转换为 true false 的意思。

这样就明确了,filter 中传入谓词函数,谓词函数的主体就是判断条件,此判断条件会对元素进行测试。

一开始的写法,实际上没有理解 filter 的本意。if 条件!delIdxList.includes(index)本身就是谓词的主体,然后 return item,那么是否保留元素就依赖于 item 是否可以转换为 true 了。很显然,false、0 这些值无法转换为 true。

之前看到的写法是:www.cnblogs.com/lishidefeng…

var a=[1,2,"b",0,{},"",NaN,3,undefined,null,5];
var b=a.filter(Boolean); // [1,2,"b",{},3,5]
b = a.filter(Boolean);

它等价于

b = a.filter(function (x) { return Boolean(x); });

参考: