Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct use of a "for...in" loop in javascript?

Tags:

javascript

before I ask my question I wanted to let everybody know that I appreciate the fact that there's always somebody out there willing to help, and on my end I'll try to give back to the community as much as I can. Thanks

Now, I would like to get some pointers as to how to properly take advantage of the "for...in" loop in JavaScript, I already did some research and tried a couple things but it is still not clear to me how to properly use it.

Let's say I have a random number of "select" tags in an HTML form, and I don't require the user to select an option for all of them, they can leave some untouched if they want. However I need to know if they selected none or at least one.

The way I'm trying to find out if the user selected any of them is by using the "for...in" loop. For example:

var allSelected = $("select option:selected");
var totalSelected = $("select option:selected").length;

The first variable produces an array of all the selected options. The second variable tells me how many selected options I have in the form (select tags could be more than one and it changes every time). Now, in order to see if any has been selected I loop through each element (selected option), and retrieve the "value" attribute. The default "option" tag has a value="0", so if any selected option returns a value greater than 0, I know at least one option has been selected, however it does not have to be in order, this is my loop so far:

for(var i = 0; i < totalSelected; i++){
  var eachOption = $(allSelected[i]).val();
  var defaultValue = 0;
  if(eachOption == defaultValue){
    ...redirect to another page
  }else if(eachOption > defaultValue){
    ... I display an alert
  }
}

My problem here is that as soon as the "if" matches a 0 value, it sends the user to the next page without testing the rest of the elements in the array, and the user could have selected the second or third options.

What I really want to do is check all the elements in the array and then take the next action, in my mind this is how I could do it, but I'm not getting it right:

var randomValue = 25;  
for(randomValue in allSelected){
  var found = true;
  var notFound = false
  if(found){
    display an alert
  }else{
    redirect to next page
  }
}

This loop or the logic I'm using are flawed (I'm pretty sure), what I want to do is test all the elements in the array against a single variable and take the next action accordingly.

I hope this makes some sense to you guys, any help would be appreciated.
Thanks,
JC

like image 551
jnkrois Avatar asked Jun 07 '10 19:06

jnkrois


People also ask

What is correct syntax for for in loop in JavaScript?

The for...in statements combo iterates (loops) over the properties of an object. The code block inside the loop is executed once for each property.

What is the syntax of a for loop?

Syntax of a For LoopThe for loop starts with a for statement followed by a set of parameters inside the parenthesis. The for statement is in lower case. Please note that this is case sensitive, which means the for command always has to be in lower case in C programming language.

Why for loop is used in JavaScript?

for loops are commonly used to run code a set number of times. Also, you can use break to exit the loop early, before the condition expression evaluates to false .


1 Answers

for..in (generally)

for..in loops through the names of the properties of an object. People think it loops through the indexes of an array because the indexes of an array are names of properties on the array object, but that's a misconception.

So:

var obj = {foo: 1, bar: 2};

foo and bar are names of properties, and so:

var name;
for (name in obj) {
    alert(name);
}

...will show "foo" and "bar" (in no particular order).

We'll come back to arrays in a moment. :-) Let's look at objects first.

Objects can have properties of their own, and properties they inherit from their prototype objects. The foo and bar properties above were direct properties of obj, but:

function Thing() {
}
Thing.prototype.foo = 1;

var t = new Thing();
t.bar = 2;

Now our t object has foo and bar, but foo comes from the prototype, whereas bar is its own property. In a for..in, we can check which is which:

var name;
for (name in obj) {
    alert(name + "(" + (obj.hasOwnProperty(name) ? "own" : "inherited") + ")");
}

...which will show "foo (inherited)" and "bar (own)" (in no particular order).

Objects can also have properties that are non-enumerable — they don't show up in for..in loops. This is why if you do a for..in on an array, the length property doesn't show up, because length is defined as a non-enumerable property. Nearly all of the standard properties on the standard objects are non-enumerable (including all of the ones that point to functions, like the toUpperCase property on String instances). (It used to be that only the ones in the spec could be non-enumerable, but ECMAScript 5th edition now provides ways for us to have our own non-enumerable properties.)

So, arrays. Arrays in Javascript are nothing like arrays in most other languages. (They are not contiguous blocks of memory, for one thing.) An array in Javascript is a standard object with a couple of special behaviors:

  • The length property is always set to the next number above the property name with the highest numeric value that the array objects has. So if your highest array index is 2, then length will be 3.
  • If you change length, any property whose name has a numeric value equal to or higher than the number you give length will be deleted from the object.

That, and the functions they inherit from the Array.prototype are pretty much all that's special about arrays in Javascript. All of their main functionality (storing and retrieving values) is just the standard Javascript object property behavior.

Your specific loop

For the above reasons, I wouldn't use for..in for your loop. I'd either use jQuery#each or a boring old-fashioned loop like you have. The latter would look like this:

var allSelected = $("select option:selected");
var totalSelected = allSelected.length; // <= No need to repeat the selector query
var index;
var anySelected = false;
for (index = 0; !anySelected && index < totalSelected; ++index) {
    if (allSelected[index].value !== "0") {
        anySelected = true;
    }
}
if (anySelected) {
    // do something with the selection
}
else [
    // do something about their not having picked one
}
like image 143
T.J. Crowder Avatar answered Sep 21 '22 18:09

T.J. Crowder