Week 12 Sandbox

General Brush-Up Prior to Starting Functional JavaScript Book

        
          //Rest parameter review
          //A rest (spread) parameter allows you to pass in X num of arguments, which are contained in an array
          function restReview(x, y, ...z){
            let total = 0;
            for(num of z){
              total += num;
            }
            return x + y + total;
          }
          console.log(restReview(1, 2, 3, 4, 5, 6));

          //Deconstruction review
          //Deconstruction allows you to uniquely reference elements of arrays and objects from outside via bindings
          const numOb = {a:1, b:2, c:3};
          const {c} = numOb;
          const{a, b} =numOb;
          console.log(`a=${a}, b=${b}, c=${c}`);
          const numArray = [4, 5, 6, 7];
          const [d] = numArray;
          const [,,f, g] = numArray;  //skips 4 & 5 due to extra ,
          console.log(`d=${d}, f=${f}, g=${g}`);

          //combining deconstructing with default parameters and named parameters/args
          //Allows you to pass in some, none, or all of the arguments specified by the deconstruction bindings
          function foo({a, c} = {}){
            console.log(`c=${c}`);
          }
          foo({a:1, b:2, c:3, d:4, e:5});

          function arrayFoo([a, b, ...rest] = []){
            console.log(`a=${a}, rest=${rest}`);
          }
          arrayFoo([1, 2, 3, 4, 5, 6]);

          //High-order function review
          //High-order functions are functions which either take in functions as arguments or returns them
          function outerFunction(num, someFunction){
            return someFunction(num);
          }

          function sum(nums){
            let total = 0;
            for(current of nums){
              total += current;
            }
            return total;
          }
          console.log(`total: ${outerFunction([1,2,3,4], sum)}`);
        
      

Closure & Currying

Closure in JavaScript exists in part through JavaScript's use of lexical scoping. Lexical scoping states in part that given an inner scope and and outer scope, the inner scope will have access to outer scope, but not vice versa. For example, if a function defines a let variable, and then another function inside itself, the inner function will be able to access that let. The same goes for a global variable that is defined in a script outside of a function, prior to the function definition; this variable will be available to that function.

One of the interesting parts of closure is that, as a result in part of this lexical scoping, when an outer function is passed a variable, that inner function also has reference to that variable, even if not passed into the inner function. What's more, if the outer returns the, that inner function will still hold reference to that value, even after the outer function has finished running and returned. Here is a simple example to demonstrate this, using currying:

        
          function returnFunction(x){
            return function returnSum(y){
              return x+y;
            }
          }

          const innerInstanceA = returnFunction(2);
          const innerInstanceB = returnFunction(3);

          console.log(`completing function A: ${innerInstanceA(2)}`);    //prints 4
          console.log(`completing function B: ${innerInstanceB(4)}`);    //prints 7

        
      

One To Multiple Arg Wrapper

Lets say you function which calls another function and passes in a single argument to it. What do you do if you want to use that function to call a function that takes in multiple arguments, through passing in an array, object, etc? How do you convert that single argument to multiple arguments?

One solution would be to wrap the single argument function inside of another function, which takes in a single argument, such as an array, and spreads it into multiple arguments. Then, the wrapped single argument function will have access to multiple arguments, via spreading, instead of just the array, etc. Below is an example where I use this concept to pass in a single array of two numbers to a function that requires two arguments, by wrapping the add function in a function that spreads the array passed into it.

        
          //function that prints sum of two nums
          const add = (x, y) => console.log(x + y);

          //takes in function and calls function via arg of array with two nums
          const singleArg = theFunction => theFunction([3, 9]);

          //takes in a someFunction as an arg, then returns a function that takes in a single arg,
          //then spreads that arg in the param list for someFunction
          const spreadArgs = someFunction =>
            args => someFunction(...args);

          //Single arg passes an array to spreadArgs, which returns a call to add with the array spreaded, which returns the sum via its log call
          singleArg(spreadArgs(add));