【问题标题】:JS Array.reduce : Encountering "Uncaught TypeError: Cannot read property [...] of undefined"JS Array.reduce:遇到“未捕获的类型错误:无法读取未定义的属性 [...]”
【发布时间】:2019-07-30 16:23:27
【问题描述】:

我正在尝试在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());

错误如下: Uncaught TypeError: Cannot read property 'add' of undefined

您会注意到我在 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 对象,因此应该有一个“添加”属性。为什么错误消息告诉我它未定义?

【问题讨论】:

  • 在reducerForTime函数的末尾尝试return accumulator;

标签: javascript arrays class


【解决方案1】:

累加器应保持从一次迭代到下一次迭代

累加器等于您在上一次迭代中返回的任何值。您目前没有在 reducerTime 中返回任何内容。将其更改为:

const reducerForTime = (accumulator, currentValue = new Time()) => {
  accumulator.add(currentValue);
  return accumulator;
};

【讨论】:

  • 当然!现在很明显,我看到了。 reducer 的定义与任何其他函数一样,因此需要一个返回值。谢谢!
猜你喜欢
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 2014-07-12
  • 1970-01-01
  • 2021-12-22
  • 1970-01-01
  • 2015-01-06
  • 2017-07-26
相关资源
最近更新 更多