views:

24

answers:

3

I'm working my way through the O'Reilly jQuery Cookbook. On p.65 there is an example that looks wrong to me, but I'm new to jQuery (less than a week) so I figure it is very likely that I am the one who is confused.

The code intends to get the first three items from an ordered list & do something with them; for simplicity's sake (on the book's part) in the selector, there is only one list on the page.

They give the following code (I've simplified slightly, but not in the relevant portion); the outer two layers are, of course, boilerplate (a closure so that $ will work as desired, and code to make this fire when the page loads).

(function($){
    $(document).ready(function(){
        var arr = $.map($('li'), function(item, index){
            while (index < 3)
            {
                 return $(item).html();
            }
            return null;
        });
        /* do something with the resulting array; 
           I've deliberately simplified from the book here */
        alert(arr.join(",");
    });
})(jQuery);

The explicit iteration (while) doesn't make sense to me. As I understand it, the inner anonymous function should be called once for each element of the array, so I would expect an if, not a while.

A: 

Yes, you're correct in your understanding. It's a bad example.

ScottE
+1  A: 

This loop will never be executed more than once. It is functionally equivalent to if and I'm sure that's what the author meant to write.

There's an unconfirmed errata list on the O'Reilly website.

lonesomeday
The first wrapper is not a `document.ready` handler.
Nick Craver
Nor is it. It's been a bad day!
lonesomeday
Got it. Of course, the return saves it from being actually incorrect, but 'if' would have been tremendously clearer.
Joe Mabel
A: 

That code should have an if there, a while only exists because of the return, which is a bit of an abuse of while in this case, IMO.

As an illustration with :lt(), you can shorten that whole example down to:

(function($){
  $(function(){
    var arr = $('li:lt(3)').map(function(){
      return $(this).html();
    }).get();
    alert(arr.join(",");
  });
})(jQuery);
Nick Craver
The while is saved from being infinite by the return statement. Still, really poor and potentially unsafe given slight code modification.
patrick dw
You get the same output with while or if - but if is obviously correct.
ScottE
@patrick - oops you're right, was focused on re-writing this
Nick Craver
Also, in both your example and the OP's, `item` and `index` are the wrong way round.
lonesomeday
Nick - Yet another reason why `while` here is poor. It looked infinite at first to me as well.
patrick dw
@lonesomeday - I removed `index` in the shortened version...? And they're *not* backwards, `jQuery.map()` is not the same as `.map()`: http://api.jquery.com/jQuery.map/
Nick Craver
@Nick I haven't a clue what I'm talking about. Time to give up on SO for tonight.
lonesomeday