function product(collectionArr) {
  let result = [];
  function recur(collection) {
    if (collection.length < collectionArr.length) {
      collectionArr[collection.length].forEach(value => {
        recur(collection.concat(value));
      });
    } else {
      result.push(collection);
    }
  }
  recur([]);
  return result;
}
get the cartesian product from a few arrays
@param {Array<Array<Any>>} collectionArr
@return {Array<Array<Any>>}
@example
product([[false, true], ['a', 'b', 'c'], [{}]]);
// returns [[false, 'a', {}], [false, 'b', {}], [false, 'c', {}], [true, 'a', {}], [true, 'b', {}], [true, 'c', {}]]