Вот несколько вариантов (есть и ещё; понятно, что выдумывать все возможные я не буду, как и не буду реализовывать все выдуманные):
const merge = (arr1, arr2, step) => Array
.from(
{ length: Math.min(arr1.length, 1 + arr2.length / step | 0) },
(_, i) => [ ...arr2.slice(~-i * step, i * step), arr1[i] ]
)
.flat();
или
const merge = (arr1, arr2, step) =>
[].concat(...Array.from(
{ length: Math.min(arr1.length, 1 + arr2.length / step | 0) },
(_, i) => [ arr1[i], ...arr2.slice(i * step, -~i * step) ]
));
или
const merge = (arr1, arr2, step) =>
Array.prototype.flatMap.call(arr1, (n, i) => [
...Object.assign(
i ? Array(step).fill(null) : [],
arr2.slice((i - 1) * step, i * step)
),
n,
]);
или
function merge(arr1, arr2, step) {
const len = arr2.length;
return Array.from(
{ length: len - (len % step) + 1 + len / step | 0 },
(_, i) => {
const j = i / (step + 1) | 0;
return i % (step + 1)
? arr2[i - j - 1]
: arr1[j] ?? null
});
}
Для вашего случая -
const c = merge(b, a, 5); - можете воспользоваться любой из этих функций, результаты выдадут одинаковые. Чего может и не быть с другими аргументами. Например:
Во втором массиве недостаточно элементов:
merge('ABCD', [ 1, 2, 3, 4, 5, 6, 7 ], 4)
// первая и четвёртая функции останавливаются на элементе первого массива,
// если во втором массиве не хватает элементов, на заполнение
// очередного промежутка между элементами первого массива
['A', 1, 2, 3, 4, 'B']
// вторая функция остановится после того,
// как отдаст все элементы второго массива
['A', 1, 2, 3, 4, 'B', 5, 6, 7]
// третья функция подставит дефолтные значения
// вместо недостающих элементов второго массива
['A', 1, 2, 3, 4, 'B', 5, 6, 7, null, 'C', null, null, null, null, 'D']
Или, в первом массиве недостаточно элементов:
merge('ABC', [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ], 2)
// 1, 3
['A', 1, 2, 'B', 3, 4, 'C']
// 2
['A', 1, 2, 'B', 3, 4, 'C', 5, 6]
// 4
['A', 1, 2, 'B', 3, 4, 'C', 5, 6, null, 7, 8, null]