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…


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

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.

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?

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.

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);

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 :lol:

Thanks!