You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Waiter类订单总费用计算NaN及TypeError问题?

问题分析与解决方案

看起来你已经搞定了TypeError: name.addFood is not a function的问题(通过正确匹配到对应的Waiter实例),但现在卡在了total显示NaN的问题上,核心原因其实很明确:你传给addFood的不是带price属性的Item对象,而是一串普通字符串,具体分析和修复步骤如下:

核心问题拆解

  1. 你提交表单时拿到的foodItem是下拉选项的value值(比如"Peene Primvera (14.5)"),这是个纯字符串,不是mainFood数组里定义的Item实例。
  2. 当你把这个字符串塞进waiter.order数组后,执行this.order.map(o => o.price)时,字符串根本没有price属性,所以map出来的是一堆undefined。
  3. 用reduce对undefined求和,结果自然就变成了NaN。

另外,你的代码里用到了new Item但没贴出Item类的定义,我先默认它是标准的构造类(你实际代码里要确保正确定义):

class Item {
  constructor(name, price) {
    this.name = name;
    this.price = price;
  }
}

修复步骤

1. 渲染菜单时用Item的索引作为选项value

填充menuMain下拉框的时候,别把食物名称当value,改用它在mainFood数组里的索引,这样提交时能直接拿到对应的Item实例:

// 补全菜单渲染逻辑(如果之前没写的话)
const menuMain = document.getElementById('menuMain');
mainFood.forEach((item, index) => {
  const option = document.createElement('option');
  option.value = index; // 用数组索引作为选项的value
  option.textContent = `${item.name} (${item.price})`; // 页面显示名称+价格
  menuMain.appendChild(option);
});

2. 修改表单提交逻辑,传递正确的Item对象

在onsubmit函数里,根据选中的索引从mainFood数组中取出对应的Item实例,再传给addFood:

const formEl = document.getElementById('mainForm');
const waitersEl = document.getElementById('waiters');

formEl.onsubmit = function (e) {
  e.preventDefault(); // 用这个代替return false,更符合现代JS规范
  const foodIndex = document.getElementById('menuMain').selectedIndex;
  const selectedItem = mainFood[foodIndex]; // 获取真正的Item实例
  const waiterName = waitersEl.options[waitersEl.selectedIndex].value;
  const waiter = waiters.find(({ name }) => name === waiterName);

  if (waiter && selectedItem) {
    waiter.addFood(selectedItem); // 传递Item对象而非字符串
    console.log(waiters);
  }
};

3. (可选)优化addFood方法的写法

你当前的addFood写法是可行的,不过可以调整得更灵活——如果想在order数组里存格式化后的字符串(和你期望的结果一致),可以在push时格式化,同时提取价格计算总和:

class Waiter{
 constructor (name){
 this.name = name;
 this.order = [];
 this.total = 0;
 }

 addFood = (item) => {
  // 存格式化后的字符串,和你期望的结果一致
  this.order.push(`${item.name} (${item.price})`);
  // 从字符串里提取价格数字再求和
  this.total = this.order
    .map(o => parseFloat(o.match(/\d+\.\d+/)[0]))
    .reduce((a, b) => a + b, 0);
 }
};

修复后的效果

当你两次提交"Peene Primvera"后,Waiter实例的order数组会显示["Peene Primvera (14.5)", "Peene Primvera (14.5)"],total会正确计算为14.5 + 14.5 = 29,完全符合你的预期。

内容的提问来源于stack exchange,提问作者Liam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:42:45