Day 18 of #javascript30 is about adding up playing times for videos using reduce(), some math, and a data attribute.
More compact code
I tend to prefer readable code over terse code, but I think I am starting to really like the one- or two-liners you can make with JavaScript. This assignment could be solved with just reduce()
and some math after the reduce().
Here is code that goes trough all items with a time data attribute and adds up the seconds:
const lis = Array.from(document.querySelectorAll('[data-time]'));
const totalSeconds = lis.reduce((total, li) => {
const [minutes, seconds] = li.dataset.time.split(':').map(i => parseInt(i, 10));
return total + (minutes * 60) + seconds;
}, 0);
That is actually pretty neat I think. Much better than a bunch of loops like I would have done it in the past. An interesting side effect from doing all this thorough learning of JavaScript is that I get "inspiration" that I use in PHP everyday now. I have started using filter()
, map()
, reduce()
, and sort()
more in PHP and it makes for better code there too.
"Casting" with parseInt()
and parseFloat()
In JavaScript the string concatenation operator is '+
'. So it's not easy for JS to know what you want if you say this for instance:
console.log(23 + '01');
Do you mean "2301" or "24"? JS will assume the first, so you have to "cast" your variable to something that is a number.
You might have noticed in the code snippet above that I pass a second argument to parseInt(). This is because if you have numbers that start with a '0
', then parseInt assumes that it is either octal or decimal (this depends on the browser) if you don't specify the 'radix'. A radix is the mathematical numeral system eg. '10' like our ten-based. This is a perfect source of errors, so always pass the second parameter to parseInt.
I could have used parseFloat() that does not take the radix argument but this is a good gotcha and I like being precise.