kaleoh kaleoh - 7 months ago 5
Javascript Question

Inserting an object to a global array?

Hi I am working on my first website, and I'm just starting to learn JavaScript. I have an html file with a form for a person to fill out to take an order.

I have a global array to store objects. The objects contain the name, price, and quantity of the item added to the order.

<button type="button" onclick="addToOrder('app2-amount', 'House Salad', '6')">+</button>


This is where addToOrder() is called.

And the function:

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);
}


When I print menuObject, I thought it would be out of scope, deleted. I am inserting it into a global variable, and I think it is screwing me over.

Some odd things happen when I starting putting different menu items into the array. In one case, it added 3, 6, 12, 24, etc. with each press. Kinda funny, but I'm pretty bummed.

What happens here?

Answer

You've slightly misunderstood lexical scoping in Javascript, I think.

var declarations are scoped at the function block level. That means that even though your var statement is inside of an if block, it has scope throughout the entire function, and remains defined until the function exits. They're also valid everywhere in the function (even before their declaration), due to hoisting.

If you're writing in ES6, you can also use let declarations, which are scoped to the nearest enclosing block...in your case, the if block. That'd be the behavior I think you were expecting here.

Your other issue is logical. With each pass through your function, you're using forEach to traverse your array, and then potentially pushing your new object once for every existing object in the array. That's why you're getting a geometric progression in your array length.

If your intent was 'replace the matching item in the array if it's already there, otherwise add it to the end' then there are a couple ways you can do that. Array.find is one option, but there are several approaches that'd work.