今天做了 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 的说明:
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
trueto keep the element, or tofalseotherwise.
predicate,谓词。
百度百科对谓词的解释:
谓词:在计算机语言的环境下,谓词是指条件表达式的求值返回真或假的过程。
- 这个函数谓词用于测试数组的每个元素。
- 每一次判断,返回一个值为 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); });
参考:
- MDN filter:developer.mozilla.org/en-US/docs/…
- 百度百科谓词:baike.baidu.com/item/%E8%B0…
- filter Boolean:www.cnblogs.com/lishidefeng…