JS filter高阶函数回调中push的'new'未出现在返回结果问题解析
问题解答
核心原因是Array.filter 方法在执行启动时就会固定遍历范围,不会处理遍历过程中新增的数组元素,具体逻辑拆解如下:
- 初始的
words数组长度为6,filter调用后第一时间就会把需要遍历的元素范围锁定为索引0到索引5的初始6个元素,总共只会执行6次回调函数。 - 你在每次回调里执行的
arr.push('new')确实会修改原数组,往数组末尾追加'new'元素,但这些新增元素的索引从6开始,已经超出了filter一开始锁定的遍历范围,根本不会被传入回调做长度判断,自然不可能被加入到filter返回的结果数组里。 - 你代码里的
console.log(appendedWords)打印的是filter筛选返回的新数组,不是被修改后的原数组words,当然看不到你追加的'new'。如果在filter执行完成后加一句console.log(words),就能看到原数组末尾多了6个'new'——对应6次回调每次push一个的结果。
补充说明:这是ECMAScript规范明确规定的行为,不止filter,
forEach、map等一众数组遍历方法,都默认以方法调用初始时刻的数组长度作为遍历终止条件,遍历过程中新增的元素不会被访问。非常不推荐在遍历回调里修改原数组长度,这类带副作用的写法很容易制造难以排查的逻辑bug。
你这段代码最终的运行结果:
appendedWords的值为['spray', 'limit', 'elite'],三个元素都来自初始数组,满足长度小于7的筛选条件。- 原数组
words执行完filter后长度为12,末尾追加了6个'new'元素。
内容的提问来源于stack exchange,提问作者Jay L
相关产品推荐
相关产品推荐

