为什么JavaScript的reduce()方法在数组长度为1时行为存在差异?
JS reduce() 单元素数组行为差异原因分析
这是Array.prototype.reduce()的标准设计行为,核心原因是你调用reduce时没有传入第二个参数(归约初始值)。
reduce 无初始值的执行规则
当你没有给reduce指定初始值时,会遵循以下逻辑执行:
- 数组长度为0:直接抛出类型错误
- 数组长度为1:完全不执行你传入的归约回调函数,直接返回数组内的唯一元素
- 数组长度≥2:第一次执行回调时,
prev参数取数组第1位元素,curr参数取数组第2位元素,之后按顺序迭代执行回调
对应你的示例拆解
长度为2的数组执行逻辑
var friends = [ {a:1, books: ['Bible', 'Harry']}, {a:2, books: ['War', 'Romeo']}, ] var allbooks = friends.reduce((prev, curr) => [prev.books, curr.books])
- 无初始值且数组长度>1,第一次回调正常触发:
prev= 第一个元素{a:1, books: ['Bible', 'Harry']},curr= 第二个元素{a:2, books: ['War', 'Romeo']} - 回调返回
[prev.books, curr.books],没有更多待迭代元素,最终结果符合预期
长度为1的数组执行逻辑
var friends = [ {a:1, books: ['Bible', 'Harry']} ] var allbooks = friends.reduce((prev, curr) => [prev.books, curr.books])
- 无初始值且数组长度=1,归约回调全程不执行
- 直接返回数组唯一的元素
{a:1, books: ['Bible', 'Harry']},所以你得到的是完整对象而非books属性
兼容所有数组长度的写法
只要你的归约逻辑不依赖「将第一个元素作为初始值」的默认行为,都主动传入初始值即可保证行为统一:
如果要收集所有books字段为二维数组:
var allbooks = friends.reduce((prev, curr) => { prev.push(curr.books) return prev }, []) // 第二个参数就是初始值,这里传入空数组
如果要把所有books数组合并为一维数组:
var allbooks = friends.reduce((prev, curr) => prev.concat(curr.books), [])
内容的提问来源于stack exchange,提问作者Wagner_Cateb
相关产品推荐
相关产品推荐

