Estoy tratando de enhebrar un objeto con mi función personalizada, solo lo hago con fines de práctica. Pero la función no devuelve lo que quiero.
Aquí está toda la función y el objeto al que paso.
const data = { hello: "world", is: true, nested: { count: 5 } }; const stringify = (obj, symbol, numRepeat, stringifiedObj) => { const keys = Object.keys(obj); const values = Object.values(obj); // console.log("stringified object when functino runs", stringifiedObj); // console.log("ALL KEYS", keys); // console.log("ALL VALUES", values); keys.forEach((key, index) => { // console.log(typeof obj[key]); if (typeof values[index] !== "object") { console.log(values[index]); // console.log(`{${key}: ${values[index]}}`); stringifiedObj += `${key}: ${values[index]}\n`; console.log("strinbgify inside if".toLocaleUpperCase(), stringifiedObj); } else { console.log("this is Object", obj[key]); stringify(obj[key], symbol, values, stringifiedObj); } }); return `{${stringifiedObj}}`; }; console.log("FUNCTION RETURN", stringify(data, "|-", 2, ""));Puede ignorar los parámetros symbol y numrepeat ya que los usaré más adelante.
entonces el resultado esperado es
hello: world is: true nested:{ count: 5 }pero vuelve;
hello: world is: true¿dónde estoy haciendo mal?
Esta debería ser una versión fija. Agregué algunos comentarios en el código.
Básicamente, con la recursividad, generalmente necesita return un valor que se tomará en la iteración anidada.
Array.ForEach no devuelve nada, solo ejecuta el código de cada elemento. Array.map en su lugar, devuelve el resultado.
const data = { hello: "world", is: true, nested: { count: 5 } }; const stringify = (obj, symbol, numRepeat, stringifiedObj) => { const keys = Object.keys(obj); const values = Object.values(obj); // Here you need to RETURN something, so array.map maps an array into something else and you can return a value return keys.map((key, index) => { if (typeof values[index] !== "object") { // so return here the .map iteration return stringifiedObj + `${key}: ${values[index]}\n`; // You really need that \n at the end? } else { // else, return your other string return stringify(obj[key], symbol, values, stringifiedObj); } }); // as we did -return keys.map- this one below is no longer needed //return stringifiedObj; }; console.log("FUNCTION RETURN", stringify(data, "|-", 2, ""));Puede que le guste esta técnica de análisis de tipo simple usando el switch en t?.constructor . Cada caso realiza solo lo que es necesario para la "forma" de cada tipo y recursivamente llama a stringify en los elementos secundarios del tipo. Al agregar un parámetro predeterminado depth = 1 , podemos formatear la salida usando líneas correctamente sangradas =
function stringify (t, depth = 1) { switch (t?.constructor) { case String: return `"${t.replace(/"/g, '\\"')}"` case Object: return `{${linebreak(depth)}${ Object .entries(t) .map(([k,v]) => `${k}: ${stringify(v, depth + 1)}`) .join(`,${linebreak(depth)}`) }${linebreak(depth - 1)}}` case Array: return `[${linebreak(depth)}${ t .map(v => stringify(v, depth + 1)) .join(`,\n${" ".repeat(depth)}`) }${linebreak(depth - 1)}]` default: return String(t) } } function linebreak (depth, s = " ") { return `\n${s.repeat(depth)}` } const data = { hello: "world", is: true, nested: { count: 5, any: null, with: [ "array", undefined, { object: NaN } ] } } console.log(stringify(data)) { hello: "world", is: true, nested: { count: 5, any: null, with: [ "array", undefined, { object: NaN } ] } }