JavaScript30

笔记

DEMO
GitHub

透过精简的 map()reduce() 搭配来计算影片列表总时间

作法

练习操作数组的 map()reduce(),皆为前面单元用过的方法,此篇为稍微进阶的搭配。

  1. 先使用 querySelectorAll 抓取所有 li DOM,并使用 Array.from 将 NodeList 转为 Array 后才能使用 map() 与 reduce()
1
const timeNodes = Array.from(document.querySelectorAll(".videos li"));
  1. 因为 map() 会回传一个新的操作后的数组,所以可以继续再用 .map()reduce() 接下去操作。
1
2
3
4
5
6
7
8
const seconds = timeNodes
.map(node => node.dataset.time)
.map(time => {

const [mins, secs] = time.split(":").map(parseFloat);
return mins * 60 + secs;
})
.reduce((total, second) => total + second);
  • 第一个 map() 取每个 li 上 data-time 的值。
  • 第二个 map() 透过数组解构的方式,将每个 time split(":") 成为长度为二的数组([min,sec]),这边特别的是,再透过一个 map() 塞入 parseFloat 将此数组内元素转化为数字 (也可塞入 Number),最后加总计算成秒数后回传
  • 最后透过 reduce 累加每个秒数及得到总秒数。
  1. 最后的步骤比较简单,透过简易的除法与余数来取得时:分:秒就完工了

map() reduce() 可参考之前的挑战笔记
JavaScript30-Day4

注:为什么不使用 parseInt 将数组内元素转换为数字?
可参考 这篇文章 的说明。

简单来说就是 map() 里的 callback 有三个参数(currentValue,index,array),而 parseInt 会接受到 currentValue, index 两个参数,而使用 index 来代表进制系统的数字(一般使用时没有指定通常是 10),而此 index(进制系统数值) 非彼 index(索引),当然无法操作啰,会造成 NaN。

可以简单使用 parseFloat 函数,他只接受一个参数 currentValue,或者使用 Nubmer 也可以。