Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Array.prototype.reduce(callback[, initialValue])中initialValue的取舍问题 #2

Open
fengma1992 opened this issue Apr 3, 2018 · 0 comments

Comments

@fengma1992
Copy link
Owner

fengma1992 commented Apr 3, 2018

1. blabla

众所周知,数组实例的reduce方法有callback回调函数和initialValue两个参数,其中initialValue为可选的。借用MDN中的说明:
image

initialValue用作callback函数中的第一个参数accumulator的初始值,无initialValuecallback中的accumulator取数组的第一个值,每次循环时accumulator取上一次callback函数的返回值,currentValue 取数组的下一个位置的值,在调用空数组的reduce方法时不设initialValue会抛出一个错误。

下面介绍几个reduce方法的用途:

a. 数组求和

const sum = [0, 1, 2, 3].reduce(function (accumulator, currentValue) {
  return accumulator + currentValue
}, 0)
// sum is 6

b. 实现Array.prototype.flattern

const flattened = [[0, 1], [2, 3], [4, 5]].reduce(
  function(accumulator, currentValue) {
    return accumulator.concat(currentValue)
  },
  []
)
// flattened is [0, 1, 2, 3, 4, 5]

c. 数组元素计数

const names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];

const countedNames = names.reduce(function (allNames, name) { 
  name in allNames ? ++allNames[name] : (allNames[name] = 1)
  return allNames
}, {})
// countedNames is:
// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }

2. 坑

继续说,上面提到了两个主要的reduce函数执行时的条件:

  • 数组是否为空([])
  • initialValue是否提供

这两种条件一组合,就出现四种执行情况:

a. 数组不为空 && 提供initialValue

正常执行reduce的callback函数并返回最终的accumulator

b. 数组不为空 && 不提供initialValue

  • 当数组至少有两个元素时,将数组第一个元素值赋给initialValuecallback函数的循环从index===1开始;
  • 当数组只有一个元素时,不调用callback,直接返回数组的这个元素。

c. 数组为空 && 提供initialValue

不调用callback,直接返回initialValue

d. 数组为空 && 不提供initialValue

抛出TypeError

代码说话:

const maxCallback = ( acc, cur ) => Math.max( acc.x, cur.x )

// reduce() without initialValue
[ { x: 22 }, { x: 42 } ].reduce( maxCallback ) // 42
[ { x: 22 }            ].reduce( maxCallback ) // { x: 22 }
[                      ].reduce( maxCallback ) // TypeError

其实这几个例外情况可以这样理解:
b情况的第二个条件:数组只有一个元素而不提供initialValue,reduce会将数组的这个元素赋给initialValue,此时运行状态就和 c.数组为空,提供initialValue 一样了。而数组为空,length为0,当然不会执行reduce的callback函数,会直接返回accumulator=initialValue
进一步,d.数组为空 && 不提供initialValue 中数组为空,不会执行reduce的callback函数,会直接返回accumulator=initialValue,而此时未提供initialValue,自然是报错了。

3. 结论

在数组长度未知的情况下,调用reduce方法时不提供initialValue会产生不想要的结果甚至报错。因此,我们使用reduce方法时最好是提供initialValue

注:以上代码示例均取自MDN

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant