JavaScript30 - Day 18

By Camilla Krag Jensen naxoc |

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.