Reputation: 885
I know this problem reflects my failure to fully understand the differences between an object and an array in JS, and when it is best to use both. I am looking to understand why the output of the following function is so crazy, and hopefully this will help me understand some of the finer points of Objs and arrays in JS.
//orders is an array of numbers
function myFunction(orders, callback){
var sold = []; //fixed by changing to an obj
var open = []; //fixed by changing to an obj
var reply = [];
var response = function(sold, open){
reply.push({Output: {sold:sold, open:open}});
callback(reply);
};
orders.forEach(function(id, i){
//somelogic that builds sold and open
if(i == orders.length -1) response(sold, open);
});
}
In this example sold and open are both key-value arrays. The output of response
is what I expected:
[ { Output: { sold: [Object], open: [Object] } } ]
However, if I just slightly modify this by adding a .toString()
to either array I get a massive output of tildes that ultimately results in my having to hard kill the process. The solution is obvious that I need to be passing in objects and not arrays, and use JSON.strigify()
. My question is why are these results so drastically different? Is the unexpected output a result of using the .push with a key-value array? I have had success using an array for key value pairs, but should I alternatively change reply to an object as well and drop the push method?
Upvotes: 3
Views: 250
Reputation: 678
It's important to understand that a "key-value array" in Javascript by definition means you're talking about an object. Because objects are key-value, and arrays are index-value.
Your piece of code is a little hard to read because I have no idea what input you are giving or what output you are expecting. But if I understand it correctly, you would like to return an object with two attributes: sold
and open
, so you can refer to it as reply.sold
and reply.open
. This means that reply
should be an object, with two keys: "sold" and "open". The two values for these two keys will both be an array containing orders. These don't need to be an object, because do not need keys.
You can actually define object reply
, and the two arrays reply.sold
and reply.open
in one line:
var reply = { sold: [], open: [] }
which means your response function would look like this:
var response = function(sold, open){
reply.sold.push(sold);
reply.open.push(open);
callback(reply);
};
In the end this would be the structure of reply
:
{
sold: [ order1, order2, order3, ... ],
open: [ orderA, orderB, orderC, ... ]
}
Since reply.sold
and reply.open
are now arrays, you could simply use .join(glue)
to convert them into a much more readable string:
var soldString = reply.sold.join(", ") // "order1, order2, order3, ..."
var openString = reply.open.join(", ") // "orderA, orderB, orderC, ..."
Another useful thing about using arrays in this case would be that you could actually give the orders a specific order (no pun intended). With objects, most Javascript engines will run through the attributes in alphabetical order when doing a "for in" loop. However, this is not guarantied. But when calling .forEach()
on an array, or when doing a regular for loop.
// assuming object "obj", and array "arr"
for(var key in obj) { /* order of "key" is not guarantied */ }
for(var i = 0; i < arr.length - 1; i ++) { /* "i" is always in ascending order */ }
Hope this helps a bit.
Upvotes: 1