跳至主要内容

[JS30] Day18: Tally String Times with Reduce

keywords: 時間, time, Array-like to Array, dataset, 秒數轉時分秒

今天會練習如何去把時間累加起來。

將時間累加

把 Array-like 的 Node 元素轉成 Array(Array-like to Array)

我們取得的 Node Element 它是 Array-like 的物件,而不是真的 Array,因此他沒有 Array.prototype.map 這個 function 可以使用,因此我們需要先把它轉成 Array:

方法一:使用 spread operator(...

const timeNodes = [...document.querySelectorAll('[data-time]')];

方法二:使用 Array.from()

// Array.from(<arrayLikeObject>)
const timeNodes = Array.from(document.querySelectorAll('[data-time]'));

把 data-set 的資料取出來

使用 Element.dataset.<attribute> 可以把 data-time 的值取出來。

陣列的解構賦值

在 ES6 中可以直接透過解構的方式賦值,像是下面這樣子:

let [a, b, c] = [1, 2, 3];
console.log(a, b, c); // 1, 2, 3

如此變數 a = 1, b = 2, c = 3,這是最基本的陣列解構賦值方式。

因此,我們可以用這樣的寫法:

// 使用陣列的解構賦值
const [min, sec] = time
.split(':') // ['12', '39']
.map((str) => parseInt(str)); // 把字串轉成數值

陣列的解構賦值 @ PJCHENder HackMD

使用 Array.prototype.reduce

透過 Array.prototype.reduce( callback<accumulator, currentValue, currentIndex, array>, initialValue ) 每次 return 的內容都會存到 accumulator 中,因此可以累加陣列裡的內容後回傳。

JavaScript 陣列 @ PJCHENder HackMD

程式碼

// 將 array-like 的 Node Element 轉成 Array
const timeNodes = [...document.querySelectorAll('[data-time]')];

const totalSeconds = timeNodes
.map((node) => node.dataset.time) // 把 nodeElement 的 data-time 取出來
.map((time) => {
// 把 time 全部變成秒數
const [min, sec] = time // 使用陣列的解構賦值
.split(':') // 得到字串['12', '39']
.map((str) => parseInt(str)); // 把字串轉成數值
return min * 60 + sec;
})
.reduce((totalSeconds, currentSeconds) => {
// 將所有的秒數累加
return totalSeconds + currentSeconds;
}, 0);

將秒數轉成「時:分:秒」

加總所有的秒數取得 totalSeconds 後,我們就可以將這個秒數在轉換為時分秒。

在這裡我們透過 Math.floor 達到無條件捨去的效果。而 totalSeconds % 3600 表示扣掉轉換完小時之後所剩下的秒數。

let hours = Math.floor(totalSeconds / 3600); // Math.floor 無條件捨去
let mins = Math.floor((totalSeconds % 3600) / 60);
let seconds = (totalSeconds % 3600) % 60;

console.log(hours, mins, seconds);

完成作品

Day18: Tally String Times with Reduce