You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

复刻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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 09:25:01