頁面連結:Adding Up Times with Reduce(請開啟 console 看結果)、程式碼
今天同樣不會做出作品,重點是學習 reduce(..)
--- 將 array 輸出成單一項目
可以從程式碼看到 HTML 中有許多 li
,當中又有 data-time
的屬性,而今天的任務就是將所有 data-time
的所有時間相加並格式化成(時 分 秒)
那就開始吧!
首先先列出要做的事情
取得所有 li
,但由於等一下會用到 array methods,所以要將 nodeList
轉成 array
const videos = Array.from(document.querySelectorAll('.videos li'));
還記得如何取得 dataset 資料嗎?就是 element.dataset.xxx
const seconds = videos
.map(video => video.dataset.time)
// 此使得結果是一 array,每一項都是(分:秒)的 string
這樣寫法乍看很奇怪,目的是將所有方法串成一串,而不用宣告過多變數儲存
從 dataset
中可以看到時間的格式都是(分:秒),我們可以利用 split()
將分、秒分開
const seconds = videos
.map(video => video.dataset.time)
.map(time => time.split(':'))
接下來要加總每一項結果成秒數,但記得至此分、秒都還是 string,要轉成 number 才能相加
要將 string 轉成 number 我知道的方法有二
Number(..)
parseFloat(..)
const seconds = videos
.map(video => video.dataset.time)
.map(time => time.split(':'))
.map(time => parseFloat(time[0]) * 60 + parseFloat(time[1]))
這裡是重點啦!我們要用 reduce()
來加總每一項的秒數
reduce()
的 callback 最多可以傳入 4 個參數,分別是加總、當前值、當前 index、來源的 array,除了 callback 還可以傳入初始值(非必須)。但我們今天只會用到前兩個
const seconds = videos
.map(video => video.dataset.time)
.map(time => time.split(':'))
.map(time => parseFloat(time[0]) * 60 + parseFloat(time[1]))
.reduce((total, vidSeconds) => total + vidSeconds);
如果沒有給初始值的話,JS 預設會使用 array 第一項的值作為初始值
如此一來我們就有了總秒數了!剩下
這裡需要稍微想一下要如何用「秒數」得出時、分、秒
一分鐘等於 60 秒,利用餘數概念可以得出剩餘秒數
const second = seconds % 60; // 1 分鐘 === 60 秒
%
(mod)這個符號是運算餘數的意思,舉例來說 69 % 60; // 9
一小時等於 3600 秒,利用秒數除以 3600 可以得出小時,但由於不一定是整數,所以需要取整數(小數點後代表分、秒的加總)
const hour = Math.floor(seconds / 3600);
Math.floor(..)
的意思是無條件捨去法,四捨五入是 Math.round(..)
、無條件進位法是 Math.ceil(..)
剛剛得出秒了,我們可以扣掉秒與時,剩下的就是分鐘數了
const minute = ((seconds - second) % 3600) / 60;
首先先減去秒數 -> 小時 + 剩餘分鐘 -> mod 小時(會得到剩餘秒數)-> 除以 60 就是分鐘數了~
最後印出結果就完成了!
console.log(hour, minute, second);
// 4 58 58