Рекурсия есть:
const serialize = (obj, path) => Object
.entries(obj)
.map(([ k, v ]) => {
const p = path ? `${path}[${k}]` : k;
return v instanceof Object ? serialize(v, p) : `${p}=${v}`;
})
.join('&');
Рекурсии нет:
function serialize(obj) {
const result = [];
for (const stack = [ [ obj, '' ] ]; stack.length;) {
const [ n, path ] = stack.pop();
if (n === Object(n)) {
stack.push(...Object
.keys(n)
.map(k => [ n[k], path ? `${path}[${k}]` : k ])
.reverse()
);
} else {
result.push(`${path}=${n}`);
}
}
return result.join('&');
}