for..in loop loops over non-numeric indexes “clean” and “remove” - javascript

This is something very basic I might be missing here but I haven't seen such result till now.
I have a for loop where options.headers.length is 3. And in for loop I am dynamically creating a table header. Ideally this loop should run three times for 0 1 and 2 but when I have printed index it's printing 0,1,2,clean and remove. I haven't seen clean and remove as indexes. I know this information is not sufficient enough but if you have any clue please suggest. something might be overriding this is all I am concluded too after my debugging.
for (index in options.headers)

if you don't want to iterate clean and remove then change the loop to:
for (var i=0; i< options.headers.length;i++){
//use i for getting the array data
}
if you use for (index in options.headers) it will iterate for non-numeric keys also.

don use just index (as that is = window.index = global = bad) use var index
(read more here https://www.google.pl/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=globals+javascript+bad)
you have to check does the array has it as own property or maybe its some function (more after answer)
for (var index in options.headers) {
if (options.headers.hasOwnProperty(index) {
// code here
}
}
more about #2:
let's say we have
var array = [0,1,2,3];
and besides that, extending array with function (arrays can have functions in javascript and strings too)
Array.prototype.sayHello = function() {
alert('Hello');
};
then your loop would print sayHello as part of the array, but that's not it's own property, only the arrays

I assume that options.headers is an Array?
This happens when you (or some framework you load) adds methods to the Array prototype. The "for in" loop will enumerate also these added methods. Hence you should do the loop for an array with:
for (var i = 0; i < options.headers.length; i++)
That way you will only get the real values instead of added methods.

Related

updating a JSON objects value with a for loop in Java Script

I have an array of 11 objects which contain JSON data. I wrote a function in which a new key with a zero value is added to each of the objects. Now I want to update the value of the said key in all 11 objects. The data is stored in an array2 with 11 numbers. My for loop doesn't seem to work for this, and the only way to do it (so far) is to hard code it. Does anyone has a suggestion how this can be done?
The desired outcome would be this:
array[0].new_key = array2[0];
array[1].new_key = array2[1];
The first art of the function, before the for loop with j, is for adding the new key into the original array and that part works.
for (i = 0; i < array.length; i++) {
array.map(i => i.new_key = 0);
console.log(array)
for (j = 0; j < array2.length; j++) {
array[i].new_key = array2[j];
console.log(array)
}
}
}```
I split it into two functions, I realized that I made it too complicated and it didn't made sense. I wrote a second function that only updates all the key values, so indeed, I removed the inner loop as it was not needed. Thank you for the help.
.map() does not modify the original array:
The map() method creates a new array with the results of calling a
provided function on every element in the calling array.
You will want to get the result of the map by assigning it to a variable, and see what is happening there. Right now you don't do anything with it, so it will just disappear.
While the above is true for maps, in this case the original array is being modified as we access the object's properties and modify them there.

Looping through an array of JSON objects in Javascript

I orginally was going to ask a question on why it wasn't working. But as I commented the code I realized that I could access the text array style and item was giving me the index. It took me a while to find this as the solution, however I would have much rather used item.text in the for loop. Is this [my posted answer] the valid way to loop through JSON objects in Javascript?
There's no such thing as a JSON object - once you've parsed your JSON (which is a string) you end up with simply an object. Or an array.
Anyway, to loop through an array of objects, use a traditional for loop. A for..in loop may work, but is not recommended because it may loop through non-numeric properties (if somebody has been messing with the built-in array).
In your specific case, if obj.body.items is an array then do this:
for (var i = 0; i < obj.body.items.length; i++) {
// obj.body.items[i] is current item
console.log(obj.body.items[i].text);
}
You can also, arguably, make the code a bit neater by keeping a reference directly to the array rather than accessing it via the whole obj.body. chain every time:
var items = obj.body.items;
for (var i = 0; i < items.length; i++) {
console.log(items[i].text);
}
"I would have much rather used item.text in the for loop"
In your answer - which really should've been posted as part of the question - because you are using a for..in loop your item variable is being set to each index in turn as a string, e.g., on the first iteration it will be the string "0", and strings don't have a text property so item.text doesn't work - although it should give you undefined, not null. But you can do this:
var item;
for (var i = 0; i < obj.body.items.length; i++) {
item = obj.body.items[i] // get current item
console.log(item.text); // use current item
}
That is, declare a variable called item that you set to reference the current array item at the beginning of each loop iteration.
<script type="text/javascript">
...
obj = JSON.parse(xmlhttp.responseText);
// displays the object as expected
console.log(obj);
// display the string next as expected
console.log(obj.body.next);
// displays the text of the item as expected
console.log(obj.body.items[0].text);
for (var item in obj.body.items) {
// displays the index value of the item
console.log(item);
// displays null - WHAT?? HUH?
console.log(item.text);
// displays the text - finally
console.log(obj.body.items[item].text);
}
<script>

getting the amount of properties in an object then getting the last one of them in a for loop

This should be very easy but I don't know how to do it.
I have this object:
var obj = eval(result);
Now I want to know how many properties contains to put it in a loop
var finalAmount = obj.length;
Now I go for the loop
for (var i in obj) {
--- some other code in here
Now here the problem I need to do something when the loop reaches the final property of the obj, so this is what Ive tried:
if (i+1 == finalamount){
//do something
} else {
//do something else
}
so basically using the i as a pointer to compare it to the var that contains how many items there are and when finding the final one of the loop then do something...
In this case i is not necessarily numeric, and so i+1 may not give you the desired results. You should set up a separate counter variable that you increment at the end of each loop iteration.
In your case obj must be an Array. If it is not, i+1 throws error.
The for-in loop does not ensure any sequence order, even it is an Array, it is only used to iterate unordered properties. You need traditional for(index=0;index<length;index++) (if it is an Array)
If your obj variable is an Object instead of Array, you can't get "last property" only with object data structure, it must provide more information (property order).

Problems with JavaScript "for in" loop

I have an array of objects which will be the basis for a certain menu in my website. It will be build using JavaScript:
[
{"menuName":"Contact Info","sectionName":"contacts"},
{"menuName":"Facilities","sectionName":"facilities"},
{"menuName":"Locations","sectionName":"locations"},
{"menuName":"Packages","sectionName":"packages"},
{"menuName":"Policies","sectionName":"policies"},
{"menuName":"Reviews","sectionName":"reviews"},
{"menuName":"Rooms","sectionName":"rooms"}
]
So I decided to use the "for in loop" so that I won't have to deal with indexes and lengths. I expect seven items to appear in the menu when it gets built (I'll be using <ul> and <li>).
When I was debugging and accidentally added a background color to the <li>, is when all hell broke loose. I found at least 30 empty <li> after the visible 7th menu <li>.
Why is this happening?
EDIT:
Here's the loop. The loop creates another object for another function to parse later on. (It creates an <li> with an <a> inside with properties provided by the previous array.) I know that the other function works fine because when I change this "for-in" loop to an ordinary for loop, or while loop, it works fine.
this.sectionList = function(menu, id) {
var list = new Array();
for(var i in menu) {
var listItem = {
"element" : "li",
"contains" : [{
"element" : "a",
"attr" : {
"href" : menu[i].sectionName + ':' + id
},
"contains" : menu[i].menuName
}]
}
list.push(listItem);
}
}
for in iterates over object properties. Javascript arrays are just a specific kind of object with some handy properties to help you treat them as just arrays, but they still have internal object properties .. and you don't mean to iterate over these).
So, you shouldn't use for in to iterate over arrays. This only became evident to you when you added your background colour, but it'll always be the case.
Instead, loop with a counter and array .length.
Your object gets methods and properties passed by JavaScript itself. Those are methods that every object gets when its created.
You have to use .hasOwnProperty to find only the properties and methods you assigned to the object!
for(var i in myObject){
if(myObject.hasOwnProperty(i)){
console.log(myObject.i);
}
}
Hope that helps!
Here are two articles that helped me two understand it better:
http://bonsaiden.github.com/JavaScript-Garden/#object.hasownproperty
http://javascriptweblog.wordpress.com/2011/01/04/exploring-javascript-for-in-loops/
I see no difference between the two ways of iterating your data structure in this jsFiddle: http://jsfiddle.net/jfriend00/HqLdk/.
There are lots of good reasons why you should not use for (x in array) on arrays. The main reason is that that type of iteration iterates over the properties of the object, not just the array elements. Those properties can include other properties of the array if any have been added where as the for (var i = 0; i < array.length; i++) method will never have issues with added properties because by definition, it only iterates over the array elements.
It is somewhat luck that when no additional properties have been added to the array object, that iterating over the properties happens to include just the array elements. The language does not want you to iterate array elements that way. You should iterate arrays with
for (var i = 0; i < array.length; i++).
I understand the seduction of the simpler syntax, but it is not the right way to do it.

Adding functions to javascript's Array class breaks for loops

I was looking for a way to add max/min functions to JavaScript's Array class, which seemed to be a solved problem: JavaScript: min & max Array values?. However, when I tried using that, I started getting errors from my code. It turns out that this approach doesn't work with loops.
for(i in myArray) { console.log(i) }
prints out
1
2
3
max
min
Is there another approach I can use?
The accepted solution solves your immediate problem, but extending core objects is generally a bad idea. What happens when you include a library later that uses for..in? Or when you forget months later and use the wrong approach in a different section of your code?
Another option is to wrap and extend. Create a new type that uses an instance of Array as its prototype:
function ArrayThing() {}
ArrayThing.prototype = new Array();
Now you've got an object that you can extend without affecting Array:
ArrayThing.prototype.max = function() {
return Math.max.apply(null, [].slice.call(this, 0))
}
ArrayThing.prototype.min = function() {
return Math.min.apply(null, [].slice.call(this, 0))
}
var list = new ArrayThing();
// standard array methods still work
list.push(5);
list.push(22);
list.push(0);
list.push(-14);
list.length // => 4
// as do your new custom methods
list.max() // => 22
list.min() // => -14
This won't work in every situation, but unless you're sure you really, really need an Array, this is a useful alternative.
The for...in loop is used for looping through properties of an object. If you want to get the values from your array, you can do this:
for (var i = 0; i < myArray.length; i++)
{
console.log(myArray[i])
}
for in is a common Javascript trap. Instead of behaving like a foreach from other languages, it actualy enumerates all properties in a given object.
Since Javascript Arrays happen to have a property for each index using for in works sometimes, but as you have seen, it also enumerates any other properties you add. Another issue is that the for in is not guaranteed to go through the properties in any particular order, so your results can vary depending on which browser/runtime you use.
It is safer, then, to just use a boring for loop instead. There are many for loop idioms in Javascript, so I will list some:
Regular for loop:
for(i=0; i<arr.length; i++){
Regular loop, caching the length:
for(i=0, n=arr.length; i<n; i++){
Loops over arrays of objects/NodeLists:
for(i=0; obj=arr[i]; i++){ //this works as long as the array has no falsy values
foo(obj)
You need to apply a check using hasOwnProperty.
However this needs to applied wherever you are looping.
i.e:
for(i in myArray)
{
if(arr.hasOwnProperty(i))
{
console.log(i);
}
}
There's a more modern (IE9+) way to do this now:
var g = [];
Object.defineProperty(g, "log", {
enumerable: false,
configurable: false,
writable: false,
value: function(){ console.log(this); }
});
g.push(5);
g.push(9);
var t;
for (t in g){
console.log(g[t]);
}
prints 5 and 9 but does not list the "log" function
g.log() -> echos [5,9]
The key to this working is being able to flag a property as "enumerable: false" with marks the property as something that shouldn't be iterated over.
More on Object.defineProperty here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

Categories

Resources