我正在尝试完成JavaScript30的练习。我想知道为什么我想出的解决方案不起作用。
这个想法很简单。您有一个网页,其中视频时长存储在列表中,如下所示:
<ul class="videos">
<li data-time="5:43">
Video 1
</li>
<li data-time="2:33">
Video 2
</li>
</ul>
列表中实际上有58个项目。练习是计算所有视频的总时长(换句话说,获得列表中包含的所有时长的总和)。
我有用于课程制定者解决方案的代码,它与我的解决方案采用的路径不同。当我创建“时间”类时,它将持续时间存储为秒。我了解此解决方案,但我想了解为什么我的解决方案无法正常工作。
课程随附的解决方案:
const timeNodes = Array.from(document.querySelectorAll('[data-time]'));
const seconds = timeNodes
.map(node => node.dataset.time)
.map(timeCode => {
const [mins, secs] = timeCode.split(':').map(parseFloat);
return (mins * 60) + secs;
})
.reduce((total, vidSeconds) => total + vidSeconds);
let secondsLeft = seconds;
const hours = Math.floor(secondsLeft / 3600);
secondsLeft = secondsLeft % 3600;
const mins = Math.floor(secondsLeft / 60);
secondsLeft = secondsLeft % 60;
console.log(hours, mins, secondsLeft);
我(尚未运行)的解决方案:
function Time(hours = 0, minutes = 0, seconds = 0) {
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
this.addTime = function(hours = 0, minutes = 0, seconds = 0) {
const ajout = new Time(hours, minutes, seconds);
this.add(ajout);
}
this.add = function(ajout) {
let surplus = 0;
// seconds
this.seconds += ajout.seconds;
while (this.seconds >= 60) {
this.seconds -= 60;
surplus++;
}
// minutes
this.minutes += ajout.minutes + surplus;
surplus = 0;
while (this.minutes >= 60) {
this.minutes -= 60;
surplus++;
}
// hours
this.hours += ajout.hours + surplus;
}
this.toString = function() {
return `${this.hours} h ${this.minutes} min ${this.seconds} s`;
}
}
function stringToTime (str) {
let h, m, s = 0;
const arr = str.split(':');
while (arr.length > 3) {
arr.shift();
}
if (arr.length == 3) {
h = parseInt(arr.shift());
}
if (arr.length == 2) {
m = parseInt(arr.shift());
}
if (arr.length == 1) {
s = parseInt(arr.shift());
}
return new Time(h, m, s);
}
//const reducerForTime = (accumulator, currentValue = new Time()) => accumulator.add(currentValue) || new ();
const reducerForTime = (accumulator, currentValue = new Time()) =>
{
console.log(currentValue);
//console.log(`accumulator = ${accumulator.toString()}; currentValue = ${currentValue.toString()}`);
accumulator.add(currentValue);
console.log(`accumulator after adding = ${accumulator.toString()}`);
};
const videos = document.querySelectorAll('ul.videos li');
let videoTimes = [];
for (let i = 0; i < videos.length; i++) {
videoTimes.push(stringToTime(videos[i].dataset.time));
}
console.log(videoTimes.reduce(reducerForTime).toString());
错误如下: 未捕获的TypeError:无法读取未定义的属性“ add”
您会注意到,我在reducer函数中添加了两行“ console.log”行,以尝试找出问题出在哪里。
我现在得到以下控制台输出:
Time {hours: 0, minutes: 2, seconds: 33, addTime: ƒ, add: ƒ, …}
accumulator after adding = 0 h 8 min 16 s
Time {hours: 0, minutes: 3, seconds: 45, addTime: ƒ, add: ƒ, …}
Uncaught TypeError: Cannot read property 'add' of undefined
at reducerForTime (index-START.html:239)
at Array.reduce (<anonymous>)
at index-START.html:248
reducerForTime @ index-START.html:239
(anonymous) @ index-START.html:248
它所指的行是 248 和 239 。第 248 行是调用reduce函数的那一行。第 239 行是带有accumulator.add(currentValue);
的行。我不知道为什么它不起作用,因为根据我的理解,累加器应保持一次迭代到下一次迭代,因此应该是一个Time对象,因此应该具有“ add”属性。为什么错误消息告诉我它是未定义的?
答案 0 :(得分:1)
应将累加器从一次迭代保留到下一次
累加器等于您在上一次迭代中返回的值。您当前未在reducerTime中返回任何内容。更改为:
const reducerForTime = (accumulator, currentValue = new Time()) => {
accumulator.add(currentValue);
return accumulator;
};