我有一个html文件,其中包含一个表格供个人填写以接受订单。
我有一个存储对象的全局数组。对象包含添加到订单中的商品的名称,价格和数量。
<button type="button" onclick="addToOrder('app2-amount', 'House Salad', '6')">+</button>
这是调用addToOrder()的地方。
功能:
var orderArray = [];
function addToOrder(id, nameIn, priceIn){
if (loggedIn == true){
var quantityIn = document.getElementById(id).value;
var totalForThisItem = priceIn*quantityIn;
var menuObject = {
name: nameIn,
price: totalForThisItem,
quantity: quantityIn
};
// Next we must perform a check to see if an object with the same name already exists in the order
// If it does exist, replace it with this new object.
if (orderArray.length == 0){
orderArray.push(menuObject);
}
else{
orderArray.forEach( function (item) {
if (item.name == menuObject.name){
item = menuObject;
}
else{
orderArray.push(menuObject);
}
});
}
console.log("dabs " + orderArray.toString());
}
// If user is not logged in:
else{
console.log("You are not logged in. Please log in to use this feature.");
}
console.log(menuObject);
}
当我打印menuObject时,我认为它会超出范围,删除。我将它插入到一个全局变量中,我认为这让我感到困惑。
当我开始将不同的菜单项放入数组时,会发生一些奇怪的事情。在一种情况下,每次按下它会增加3,6,12,24等。有点好笑,但我很沮丧。
这里发生了什么?
答案 0 :(得分:3)
我认为你在Javascript中略微误解了词法作用域。
var
声明的作用域是功能块级别。这意味着即使您的var
语句位于if
块内,它也具有整个函数的作用域,并且在函数退出之前一直保持定义。由于hoisting,它们在函数的任何地方(甚至在声明之前)都是有效的。
如果你在ES6中写作,你也可以使用let
declarations,其范围限定在最近的封闭块...在你的情况下,if
块。这就是我认为你在这里期待的行为。
你的另一个问题是合乎逻辑的。每次通过函数时,您都使用forEach
遍历数组,然后可能会为数组中的每个现有对象推送一次新对象。这就是为什么你的阵列长度有几何级数的原因。
如果您的意图是'替换数组中的匹配项(如果它已经存在),否则将其添加到结尾'然后有几种方法可以做到这一点。 Array.find是一种选择,但有几种方法可行。