// Array Applicative Array.prototype.ap = function ( ...args ) { const loop = ( acc , [ x , ...xs ] ) => x === undefined ? [ this [ 0 ] ( ...acc ) ] : x.chain ( a => loop ( acc.concat ( [ a ] ) , xs ) ) return loop ( [] , args ) } // Array Monad Array.prototype.chain = function chain (f) { return this.reduce ( ( acc , x ) => acc.concat ( f (x) ), [] ) } // the hard work is already done const combinations = ( ...xxs ) => [ ( ...xs ) => xs ] .ap ( ...xxs ) console.log ( combinations ( array1 , array2 , array3 ) ) // [ [ 'a1', 'a2', 'a3' ], // [ 'a1', 'a2', 'b3' ], // [ 'a1', 'a2', 'c3' ], // [ 'a1', 'b2', 'a3' ], // [ 'a1', 'b2', 'b3' ], // [ 'a1', 'b2', 'c3' ], // [ 'b1', 'a2', 'a3' ], // [ 'b1', 'a2', 'b3' ], // [ 'b1', 'a2', 'c3' ], // [ 'b1', 'b2', 'a3' ], // [ 'b1', 'b2', 'b3' ], // [ 'b1', 'b2', 'c3' ], // [ 'c1', 'a2', 'a3' ], // [ 'c1', 'a2', 'b3' ], // [ 'c1', 'a2', 'c3' ], // [ 'c1', 'b2', 'a3' ], // [ 'c1', 'b2', 'b3' ], // [ 'c1', 'b2', 'c3' ], // [ 'd1', 'a2', 'a3' ], // [ 'd1', 'a2', 'b3' ], // [ 'd1', 'a2', 'c3' ], // [ 'd1', 'b2', 'a3' ], // [ 'd1', 'b2', 'b3' ], // [ 'd1', 'b2', 'c3' ] ]
.concat()you're looking for.