Search code examples
javascriptfunctionfor-loopcall

Taking apart a Function Expression - Struggling with a Couple Lines/Parameters


So I'm looking at a piece of code that is confusing me despite reading an explanation or two:

Here's the code..

var puzzlers = [
  function (a) { return 8*a - 10; },
  function (a) { return (a-3) * (a-3) * (a-3); },
  function (a) { return a * a + 4; },
  function (a) { return a % 5; }
];

var start = 2;

var applyAndEmpty = function (input, queue) {
  var length = queue.length;
  for (var i = 0; i < length; i++) {
    input = queue.shift()(input);
  }
  return input;
};

alert(applyAndEmpty(start, puzzlers));

I understand most of it but a breakdown would be great, what really boggles me is the beginning and end of this line input = queue.shift()(input); I know it's using input to store the outcome, but why? and why is there an input parameter on the end as well?

PS This line alert(applyAndEmpty(start, puzzlers)); I know calls the function then alerts it. Why do I have to call a function before I can alert/console log etc it? Is this because it isn't IIFE and so theres nothing to actually alert until the function has been called? Its quite like an 'on' button?

Sorry this is long, thanks in advance!


Solution

  • I've slightly edited the code in the for loop for clarity.

    // This array contains 5 items, each item is a function which takes a single param and returns a number.
    var puzzlers = [
      function (a) { return 8*a - 10; },
      function (a) { return (a-3) * (a-3) * (a-3); },
      function (a) { return a * a + 4; },
      function (a) { return a % 5; }
    ];
    
    // The start value is 2.
    var start = 2;
    
    var applyAndEmpty = function (input, queue) {
      // Get the number of items in the queue.
      var length = queue.length;
      // Iterate over all the items in the queue.
      for (var i = 0; i < length; i++) {
        // Remove the item at index 0 from the queue, the item is stored in the var.
        var itemMethod = queue.shift();
        // Execute the method, pass it the current value as input param. The result 
        // of the method will be placed back into the input variable.
        input = itemMethod(input);
      }
      // Return the modified input value.
      return input;
    };
    
    // Runs the applyAndEmpty method and shows the output in an alert.
    alert(applyAndEmpty(start, puzzlers));
    
    // The breakdown of the for loop:
    // i = 0, input = 2 -> return 8 * 2 - 10 = 6
    // i = 1, input = 6 -> return (6-3) * (6-3) * (6-3) = 27
    // i = 2, input = 27 -> return 27 * 27 + 4 = 733
    // i = 3, input = 733 -> return 733 % 5 = 3
    // And thus the alert says three.

    If you don't place the result of the current itemMethod back into input it means you will call each method from puzzlers with the value 2. The result of applyAndEmpty would no longer be 3 but just be 2 as the input variable is never changed. So if you don't store the result of calling the puzzler methods you might as well skip them altogether and just return the input param immediately.