复刻JSON.stringify遇报错,求排查对象与数组代码问题
复刻JSON.stringify方法的报错问题排查
我正在手动实现JSON.stringify方法,目前遇到报错但信息被截断,无法定位问题。暂时注释了嵌套数组/对象的递归代码(打算单独测试递归逻辑),以下是处理数组与对象的核心代码片段:
if (Array.isArray(input)) { var toJSON = '['; var key = 0; function toString() { if (input.length === 0) { return '[]'; } if (key < input.length) { // if (Array.isArray(input[key]) || typeof input[key] === 'object') { // toJSON += stringifier(input[key]); // } if (input[key] === null || typeof input[key] === 'function' || input[key] === undefined) { toJSON += 'null'; } if (typeof input[key] === 'number' || typeof input[key] === 'boolean') { toJSON += `${input[key]}`; } if (typeof input[key] === 'string') { toJSON += `"${input[key]}"`; } key++; if (key < input.length) { toJSON += ','; } toString(); } } toString(); return toJSON + ']'; } if (typeof input === 'object') { if (Object.keys(input).length === 0) { return '{}'; } var toJSON = '{'; for (var key in input) { toJSON += `"${key}":`; // if (Array.isArray(input[key]) || typeof input[key] === 'object') { // toJSON += stringifier(input[key]); // } if (input[key] === null || input[key] === undefined || typeof input[key] === 'function') { toJSON += `null`; } else if (typeof input[key] === 'number') { toJSON += `${input[key]}`; } else if (typeof input[key] === 'string') { toJSON += `"${input[key]}"`; } if (key != Object.keys(input)[Object.keys(input).length - 1]) { toJSON += ','; } } return toJSON + '}'; }
另外,取消递归代码注释后,原本能正常运行的数组处理逻辑也开始报错,报错提示分别为:
Maximum call stack size exceeded(调用栈溢出)Cannot convert undefined or null to object
核心问题排查与修复建议
1. 数组递归导致的栈溢出与变量污染
- 数组处理使用递归
toString()调用,当数组元素较多时会直接触发栈溢出,JavaScript调用栈深度有限,递归遍历远不如循环安全。 - 递归过程中共享
key变量,开启递归后处理嵌套数组/对象时,外层的key会被内层递归修改,进而引发无限递归或遍历顺序混乱。 - 修复:将递归改为循环
if (Array.isArray(input)) { if (input.length === 0) return '[]'; const parts = []; for (const item of input) { if (item === null || typeof item === 'function' || item === undefined) { parts.push('null'); } else if (typeof item === 'number' || typeof item === 'boolean') { parts.push(`${item}`); } else if (typeof item === 'string') { parts.push(`"${item}"`); } else if (typeof item === 'object') { parts.push(stringifier(item)); } } return `[${parts.join(',')}]`; }
2. 对象分支的null处理漏洞
typeof null返回'object',开启递归后若传入null到对象分支,Object.keys(null)会直接抛出Cannot convert undefined or null to object错误,因为null不是可枚举对象。- 修复:先排除
null的情况if (typeof input === 'object' && input !== null) { // 显式排除null const keys = Object.keys(input); if (keys.length === 0) return '{}'; const parts = []; for (const key of keys) { const value = input[key]; let valueStr; if (value === null || typeof value === 'function' || value === undefined) { valueStr = 'null'; } else if (typeof value === 'number' || typeof value === 'boolean') { valueStr = `${value}`; } else if (typeof value === 'string') { valueStr = `"${value}"`; } else if (typeof value === 'object') { valueStr = stringifier(value); } parts.push(`"${key}":${valueStr}`); } return `{${parts.join(',')}}`; }
3. 对象遍历的逗号判断逻辑错误
for...in遍历对象的键顺序不一定和Object.keys()一致(尤其是包含数字键的对象),导致最后一个元素可能错误添加逗号;且每次循环调用Object.keys(input)会重复计算,浪费性能。- 修复:提前获取所有键,使用数组收集片段后用
join(',')拼接(如上面修复代码所示),彻底避免逗号判断错误。
内容的提问来源于stack exchange,提问作者Codingenthusiast
相关产品推荐
相关产品推荐

