Копия ответа le_m для непосредственного захвата массивов массивов:
function *combinations(arrOfArr) {
let [head, ...tail] = arrOfArr
let remainder = tail.length ? combinations(tail) : [[]];
for (let r of remainder) for (let h of head) yield [h, ...r];
}
Надеюсь, это сэкономит чье-то время.