title: Why is JQuery return acting the way it is?
body: <p>I am creating a silverstripe portal for moodle; the below code is for using silverstripe avatars in moodle.</p>
  
  <p>To do this I created a a JQuery script to grab the image from silverstripe site (which is named a users moodle id) and replace the moodle one, with a fall back to moodle default pic if it doesn't exist.</p>
  
  <pre><code>$(".userpicture").each(function() {
      $(this).attr("src", function(i, origValue){
          $(this).attr( "onerror", "this.onerror=null;this.src=\'" + origValue + "\'");
  /*code for generating imgsrc */
          return imgsrc;
      });
  });
  </code></pre>
  
  <p>Worked fine, but I could only have it work for one file extension.
  So after trying many different methods of testing a url for a valid image I was able to alter my code to work for all extensions with use of a new image object. Or so I thought. This is where my question really comes into play.</p>
  
  <p>The below code, regardless if the image is jpg or png it will test all the way to bmp and return that:</p>
  
  <pre><code>$(".userpicture").each(function() {
      $(this).attr("src", function(i, origValue){
          $(this).attr( "onerror", "this.onerror=null;this.src=\'" + origValue + "\'");
  /*code for generating imgsrc */
  
          var image = new Image();
  
          image.src = imgsrc + ".jpg";
          if(image.width) {
             return imgsrc + ".jpg";          
          } else {
              image.src = imgsrc + ".png" ;
  
              if(image.width) {
                 return image.src;
              }  else {
                 image.src = imgsrc + ".gif" ;
                 if(image.width) {
                    return image.src;
                 }  else {
                    image.src = imgsrc + ".bmp" ;
  
                    if(image.width) {
                        return image.src;
                    }
                }
             }
         }
      });
  });
  </code></pre>
  
  <p>Why does it act like this? Surely the return statement should end the function and return?</p>
  
  <p>My search for an answer brought me to many explanations about .each() function and how it has unique rules around the return statement, which at first I thought explained it but the return statements aren't tied to the .each() function but rather the function inside that .attr() so it couldn't possibly be that.</p>
  
  <p>I am utterly confused by this.</p>
  
  <p>To make matters more confusing is that I created a working solution by creating a new image object for each test. This somehow makes it stop once it has found a valid image and not continue the testing.</p>
  
  <pre><code>var image = new Image();
  image.src = imgsrc + ".jpg";
      if(image.width) {
          return imgsrc + ".jpg";
      } else {
          var image2 = new Image();
          image2.src = imgsrc + ".png" ;
  
          if(image2.width) {
              return image2.src;
          }  else {
              var image3 = new Image();
              image3.src = imgsrc + ".gif" ;
  
              if(image3.width) {
                  return image3.src;
              }  else {
                  var image4 = new Image();
                  image4.src = imgsrc + ".bmp" ;
  
                  if(image4.width) {
                      return image4.src;  
                  }
  </code></pre>
  
  <p>But again why is this? Does it have something to do with the image object? Even if that were the case the return statements in the original code should still have worked?</p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>Thanks to the comments from Felix Kling and charlietft I have learnt that it is because the request is asynchronous and was completing before the images were loaded. And the second code was only appearing to work due to caching of the images.</p>
  
  <p><strong>EDIT2:</strong></p>
  
  <p>Learning why this isn't possible I re-evaluated what I wanted, and changed my thinking and have come up with this working solution:</p>
  
  <pre><code> var startExt = "jpg";
  $(".userpicture").each(function() {
  
  
      changeImage($(this),startExt);
  
   });
  
   function changeImage(item, ext){
          $(item).attr("src", function() {
  
          if( ext === "jpg") {
              item.attr( "onerror", "changeImage( $(this), \'png\')");
          } else if( ext === "png") {
              item.attr( "onerror", "changeImage( $(this), \'gif\')");
          } else if( ext === "gif") {
              item.attr( "onerror", "changeImage( $(this), \'bmp\')");
          } 
  
          /*  Code to create img url */
  
          return imgurl + "." + ext;
  
          });
      }
  </code></pre>
  
  <p>As you can see I opted for a recursive call onerror whenever an extension failed, in opposed to testing all the extensions for a valid url.
  Still not 100% happy with it, but it's better than it was and I feel I learnt more about JQuery.</p>