如何解决Waiter类订单总费用计算NaN及TypeError问题?
问题分析与解决方案
看起来你已经搞定了TypeError: name.addFood is not a function的问题(通过正确匹配到对应的Waiter实例),但现在卡在了total显示NaN的问题上,核心原因其实很明确:你传给addFood的不是带price属性的Item对象,而是一串普通字符串,具体分析和修复步骤如下:
核心问题拆解
- 你提交表单时拿到的
foodItem是下拉选项的value值(比如"Peene Primvera (14.5)"),这是个纯字符串,不是mainFood数组里定义的Item实例。 - 当你把这个字符串塞进
waiter.order数组后,执行this.order.map(o => o.price)时,字符串根本没有price属性,所以map出来的是一堆undefined。 - 用
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
相关产品推荐
相关产品推荐

