0

I have the following js script. It uses alert to count the days of the week day 0 Monday ... day 6 Saturday. i starts with 0 since this is js.

<script>
var days = ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat'];
var message = "";
for (i in days){ message += 'Day ' + i +'is ' +days[i] +'\n';}
alert(message);
</script>

I'm trying to edit i so that it begins counting from 1.

In my for ...in loop, when I increment i (i++) I get day 6 is undefined (for Saturday). When I go decrement i (i--) I get day 0 is undefined.

My questions are

1) What is the logic behind the undefined results? i is simply the counting mechanism. days is the array

 //incremented i
 for (i in days){ message += 'Day ' + I++ +'is ' +days[i] +'\n';}

 //decremented I
 for (i in days){ message += 'Day ' + I-- +'is ' +days[i] +'\n';}

2) How should I write this script to have it read day 1 is Sun...day 7 is Sat (if it can be done).

chignon
  • 19
  • 1
  • 1
  • 7
  • 2
    I don't see you using an increment or decrement and you should really be using a property [`for`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for) loop instead of a `for..in` loop. – Mike Cluck Jan 21 '16 at 23:17
  • 2
    Please, don't use `for..in` to iterate over arrays. – Cᴏʀʏ Jan 21 '16 at 23:20
  • @cory can you elaborate on this? I'm actually going through a tutorial. relatively new at js – chignon Jan 21 '16 at 23:22
  • As @Point pointed (ha!) out in their answer, JavaScript makes no guarantees on the order of elements when using `for...in`, which in itself was meant for iterating over the properties in an object, not the elements in an array. – Cᴏʀʏ Jan 21 '16 at 23:23

3 Answers3

4

Use a for loop with an index:

for (var i = 0; i < days.length; ++i)
  message += 'Day ' + (i + 1) +' is ' + days[i] +'\n';

Or use .forEach:

days.forEach(function(day, dayNumber) {
  message += 'Day ' + (dayNumber + 1) +' is ' + day +'\n';
});

Your code is using the ++ or -- operators, which actually change the value of i. Those operators are intended for that purpose. That's why you're getting the undefined values, because the subsequent reference to days[i] can be before (-1) or after (7) the beginning or end of the array. The subexpression i + 1 (or, in the .forEach() version, dayNumber + 1) does not change the value of the variable.

The for ... in loop should generally not be used when you're iterating through the numerically-indexed properties of an array object. JavaScript (strictly speaking) doesn't even guarantee that the iteration sequence of for ... in will be in any particular order.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • Not sure why you got downvoted, this is certainly the way to go IMO. – Cᴏʀʏ Jan 21 '16 at 23:22
  • @Cᴏʀʏ these things just happen :) – Pointy Jan 21 '16 at 23:23
  • 1
    I did not down vote but maybe because this answer misses: "What is the logic behind the undefined results? i is simply the counting mechanism. days is the array?" ...It sounds like the OP is trying to increment i to output the day number but is forgetting that i is needed to grab the correct index in the array. – Blizzardengle Jan 21 '16 at 23:24
  • @Blizzardengle yes I am curious as to why that happens. i++/-- impacts days variable...and I don't see why that should happen. – chignon Jan 21 '16 at 23:28
  • @Pointy I notice dayNumber is not initialized. Should I? – chignon Jan 21 '16 at 23:31
  • @chignon i think you left it out of your code but are you instrumenting days inside the loop? If so update your code here so people see that and can show you how to fix it. Long story short i++ or i-- is changing the value of i completely. So if your on 1 and then do i++ in the loop i now equals 2 and depending on your loop it may get auto incremented so now i=3 and its only gone through the loop once. ANSWER: just put i + 1 in the string your building in the loop, dont use ++ or -- – Blizzardengle Jan 21 '16 at 23:33
  • @Pointy you might want to add more to your answer to clarify things for the OP. See my comments for what he is misunderstanding. – Blizzardengle Jan 21 '16 at 23:34
  • @Pointy for loop approach didn't work for me...basically I just get a black space... – chignon Jan 21 '16 at 23:39
  • @chignon no you don't need to initialize `dayNumber` in the `.forEach()` example - the `.forEach` mechanism will set it for you. It's a parameter to the callback function. – Pointy Jan 22 '16 at 00:12
1

It looks like it's working here.

you were missing a space here: 'is ' +days[i] +'\n';

You should switch to a proper for loop anyway:

for (var i = 0; i < days.length; i++) {
  message += 'Day ' + i + ' is ' + days[i] + '\n';
}

Here is a good post describing why

Community
  • 1
  • 1
Pabs123
  • 3,385
  • 13
  • 29
0

    var days = ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat'];
    var message = "";
    for (i in days){ message += 'Day ' + (parseInt(i)+1) +' is ' +days[i] +'\n';}
    alert(message);

use i+1 to start with 1

Sachin
  • 1,208
  • 1
  • 10
  • 20
  • actually I tried that...it basically just adds to each number. literally I get 01, 11,21,... 61 . – chignon Jan 21 '16 at 23:24
  • 1
    The `for...in` construct will loop through the *properties* in an array, which are strings.. It also includes things like `length`. – Mike Christensen Jan 21 '16 at 23:26
  • @MikeChristensen for...in seems to be polite this time... not including other properties – Sachin Jan 21 '16 at 23:30
  • @MikeChristensen you're right that `for ... in` is the wrong way to iterate through arrays, but the iteration won't include the "length" property because it's not an enumerable property. – Pointy Jan 22 '16 at 00:13
  • @Pointy - Ah, I could have sworn I've seen a `length` property in an iteration of some sort.. Maybe it was a different object, or some old browser years ago. – Mike Christensen Jan 22 '16 at 15:57
  • @MikeChristensen the first time I tripped over it was when somebody added Prototype.js to our application :) That library (somewhat notoriously) added stuff to the Array prototype that made `for ... in` not work properly at all. Nowadays it's possible to create your own non-enumerable properties, and soon the ES2015 "Symbol" stuff will make it easier to confidently avoid collisions and cross-library foot-stomping. – Pointy Jan 22 '16 at 17:11