SitePoint Sponsor

User Tag List

Results 1 to 5 of 5
  1. #1
    SitePoint Enthusiast
    Join Date
    Jan 2012
    Posts
    28
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Question Having difficulties with a callback function

    I'm currently practicing on passing functions as arguments inside of other functions, using them as callbacks.

    Here's my code...

    Code JavaScript:
    var iceCreamFlavors = function (add1, add2, checkString) {
        var addFlavors = ['Chocoloate', 'Vanilla', 'Cookies', 'Mint', 'Cookie Dough'],    
            loop,
            args = arguments.length;    
     
        if (typeof checkString !== 'function') { 
            checkString = false;
        }
        for (loop = 0; loop < args; loop++) {
            if (checkString) {
                checkString(add1, add2);    
                addFlavors.push(checkString(add1, add2));   .
            }
        }
        return addFlavors; 
    };
     
    var flavorCheck = function (check) {  
        if (typeof check === 'string') {    
            return check;
        }
        return false;
    };
     
    iceCreamFlavors('Almond', 'Cotton Candy', flavorCheck);

    Here's my execution: http://jsfiddle.net/utXLu/1/

    The code itself works partially correct as I expect it to. The problem here is that the second argument that's passing as Cotton Candy from the iceCreamFlavors invocation isn't being recognized and it's being passed (copied) as the first argument.

    Can anyone help?

    Thanks

  2. #2
    SitePoint Wizard bronze trophy Jeff Mott's Avatar
    Join Date
    Jul 2009
    Posts
    1,313
    Mentioned
    19 Post(s)
    Tagged
    1 Thread(s)
    The value that you push to addFlavors is the return value of checkString, and checkString will only ever return the value of its first argument.

    Also, you're looping through the arguments as if you intended to allow an unlimited number of arguments, but inside the loop you're explicitly referencing only the first two named arguments. The value "loop" is never actually used anywhere inside your loop.
    "First make it work. Then make it better."

  3. #3
    SitePoint Enthusiast
    Join Date
    Jan 2012
    Posts
    28
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks, Jeff. I've removed the for-loop. I've updated it.

    Is there a way around this, for the the checkString function return values from multiple arguments?

  4. #4
    SitePoint Wizard bronze trophy Jeff Mott's Avatar
    Join Date
    Jul 2009
    Posts
    1,313
    Mentioned
    19 Post(s)
    Tagged
    1 Thread(s)
    The easiest way would be to separate it into two separate calls.

    addFlavors.push(checkString(add1));
    addFlavors.push(checkString(add2));


    But, to be honest, there are a number of other things I would change. For example, if one of the flavors is indeed not a string, then you'll be adding the false value onto your list of ice cream flavors. The for loop could have stayed in if you intended to loop through any number of arguments. And even the naming is a little strange -- the function to add flavors is called "iceCreamFlavors", and the list of ice cream flavors is called "addFlavors".

    If you'd like to look at another approach, here's how I might write it.

    Code JavaScript:
    function addFlavors(iceCreamFlavors /* no more named arguments, because there can be any number of them */) {
        // Optionally, the last argument can be a callback to filter the flavors
        var flavorFilter, argumentsLength;
        if (typeof arguments[arguments.length - 1] === 'function') {
            flavorFilter = arguments[arguments.length - 1];
            argumentsLength = arguments.length - 1;
        } else {
            flavorFilter = null;
            argumentsLength = arguments.length;
        }
     
        // Loop through the arguments. But skip the first argument, 
        // because that will always be the list of ice cream flavors we're adding to.
        for (var i = 1; i < argumentsLength; i++) {
            var flavor = arguments[i];
     
            // If there's no filter, or if there is a filter but this flavor passes, 
            // then add this flavor to the list of ice cream flavors.
            if (!flavorFilter || flavorFilter(flavor)) {
                iceCreamFlavors.push(flavor);
            }
        }
     
        // We modified the ice cream flavors array directly, 
        // so there's no need to return it.
    }
     
    // This filter callback merely returns true or false 
    // to indicate if the passed flavor should be included or skipped.
    function myFlavorFilter(flavor) {
        if (flavor === 'Anchovies') {
            // Skip the anchovies
            return false;
        } else {
            // Everything else is OK
            return true;
        }
    }
     
    var iceCreamFlavors = ['Chocoloate', 'Vanilla', 'Cookies', 'Mint', 'Cookie Dough'];
     
    addFlavors(iceCreamFlavors, 'Almond', 'Anchovies', 'Cotton Candy', myFlavorFilter);
     
    console.log(iceCreamFlavors);
    "First make it work. Then make it better."

  5. #5
    SitePoint Enthusiast
    Join Date
    Jan 2012
    Posts
    28
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Red face

    Thanks, Jeff. I will be looking at your code and studying it, for me be a better programmer. I was just playing around in my code, that's why the naming is a little strange

    Thanks!


Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •