1

Using the following code, I'm getting this error RewardPurchases.PurchasesArray[i].Student_Name is undefined:

$('button#random').click( function() {
    var Num = Math.floor(Math.random() * Total+1);
    Num--;

    for (var i in RewardPurchases.PurchasesArray) {
/* --------> */     
        $('#display').text("Ticker number " + Num + " in the LEAP database belongs to...\n\n\n" + RewardPurchases.PurchasesArray[i].Student_Name.toUpperCase() + " (" + TutorGroup + ")").show().delay(300);

        if (i == Num) {
            var TutorGroup = '';

            Frog.API.get('timetable.getClasses',
            {
                'params': {'student': RewardPurchases.PurchasesArray[i].Student_ID },
                'onSuccess': function(data) {
                    for (var i = 0; i < data.length; i++) {
                        if (data[i].subject.name == "Tut Period") {
                            TutorGroup = data[i].name.replace("/Tp", "");
                        }
                    }
                }
            });

            $('#display').animate({'font-size': 36}, 1500, function() {
                $(this).prepend('<p>!!! WINNER !!!</p>');
            });

            alert("Ticker number " + Num + " in the LEAP database belongs to...\n\n\n" + RewardPurchases.PurchasesArray[i].Student_Name.toUpperCase() + " (" + TutorGroup + ")");
        }
    }
} );

However, if I move this line $('#display').text(... as follows, the error disappears:

$('button#random').click( function() {
    var Num = Math.floor(Math.random() * Total+1);
    Num--;

    for (var i in RewardPurchases.PurchasesArray) {

        if (i == Num) {
            var TutorGroup = '';
/* --------> */         
            $('#display').text("Ticker number " + Num + " in the LEAP database belongs to...\n\n\n" + RewardPurchases.PurchasesArray[i].Student_Name.toUpperCase() + " (" + TutorGroup + ")").show().delay(300);

            Frog.API.get('timetable.getClasses',
            {
                'params': {'student': RewardPurchases.PurchasesArray[i].Student_ID },
                'onSuccess': function(data) {
                    for (var i = 0; i < data.length; i++) {
                        if (data[i].subject.name == "Tut Period") {
                            TutorGroup = data[i].name.replace("/Tp", "");
                        }
                    }
                }
            });

            $('#display').animate({'font-size': 36}, 1500, function() {
                $(this).prepend('<p>!!! WINNER !!!</p>');
            });

            alert("Ticker number " + Num + " in the LEAP database belongs to...\n\n\n" + RewardPurchases.PurchasesArray[i].Student_Name.toUpperCase() + " (" + TutorGroup + ")");
        }
    }
} );

I don't understand why this is the case? i isn't being defined by the if statement?

I'm trying to display each name in an array, before picking a random name and displaying it in a large font with "WINNER!" above it.

Thanks in advance,

5
  • Are you certain all the objects in your array have the Student_Name property? You may have some other objects in your array. Commented Feb 28, 2012 at 15:54
  • 1
    Have you considered that the value "Student_Name" of RewardPurchases.PurchasesArray[i]. might be undefined ? Commented Feb 28, 2012 at 15:54
  • have you tried logging i to see what it's values are in both cases? Is there any chance your inner loop is overwritting the outer loops value for i? Commented Feb 28, 2012 at 15:54
  • My initial thought is the error disappears because the offending line is inside of the if (i == Num) block. Check to make sure that the code inside of the if block is actually getting executed, then update your question. This will not solve the problem, but it will help track it down. Commented Feb 28, 2012 at 15:55
  • 2
    What do you get if you alert/log i before the error occurs? I guess it's referring to some prototype function (which is why not to use for in on arrays). Commented Feb 28, 2012 at 15:55

2 Answers 2

2

Using for .. in isn't the greatest practice in situations like these. It does a deep dredge of ALL object properties, including functions belonging to the prototype.

The reason why only $('#display').text(... causes you issues is that you try to use a property of a property RewardPurchases.PurchasesArray[i]. Elsewhere, you use it by itself, which won't fail, it will just silently return undefined in those cases. (a.k.a., 'params': {'student': RewardPurchases.PurchasesArray[i].Student_ID }.)

Using a test that you wrap all the code inside your for .. in loop, typeof RewardPurchases.PurchasesArray[i] === 'object' && typeof RewardPurchases.PurchasesArray[i] !== null should do the trick, ensuring that each property that you use in your iterations is simply an object, and not a function or some "scalar" value.

NB: You can also use RewardPurchases.PurchasesArray[i].hasOwnProperty('propertyName'), but it isn't supported universally in all browsers, so the above example I gave is safer and works for your purpose.

Sign up to request clarification or add additional context in comments.

2 Comments

I agree that this is likely the problem, but a better solution would be to not use for ... in at all.
True. If it's a numerically indexed array, then there's really no reason to use for .. in. However, for .. in is the only way to iterate over object properties. In this case, it doesn't look like he's trying to do so... so, yes, for would be a better choice here, most likely.
1

What is the integrity of your array like?

//RewardPurchases.PurchasesArray
[0] undefined
[1] { Student_Name: undefined }
[2] { Student_Name: 'Bob' }

The above are all valid in an array. [0] and [1] will both give you the error you received.

If PurchasesArray is not an array but an object - then you need to do a check inside your loop.

for (var i in RewardPurchases.PurchasesArray) {
   if(!RewardPurchases.PurchasesArray.hasOwnProperty(i)) {
     continue;
   }

   //rest of code...
}

3 Comments

Depending on his need for cross-browser support, hasOwnProperty possibly/probably isn't the best choice.
Was about to say, though, he can add it, much like indexOf for arrays. Stand corrected. :)
I retracted my comment since it introduced a new argument - extending the Object.prototype :p But yes, he could create a shim for checking if this were an issue... always have to be thinking about cross-browser issues =/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.