Skip to content

2775. 将 undefined 转为 null

2775. 将 undefined 转为 null

ts
type JSONValue =
  | null
  | boolean
  | number
  | string
  | JSONValue[]
  | { [key: string]: JSONValue }
type Value =
  | undefined
  | null
  | boolean
  | number
  | string
  | Value[]
  | { [key: string]: Value }

type Obj1 = Record<string, Value> | Array<Value>
type Obj2 = Record<string, JSONValue> | Array<JSONValue>

function undefinedToNull(obj: Record<any, any>): Record<any, any> {
  if (obj === undefined) return null
  if (typeof obj !== 'object' || typeof obj === null) return obj
  for (const key in obj) {
    obj[key] = undefinedToNull(obj[key])
  }
  return obj
}

/**
 * undefinedToNull({"a": undefined, "b": 3}) // {"a": null, "b": 3}
 * undefinedToNull([undefined, undefined]) // [null, null]
 */

JSON 的 undefined 问题

JavaScript 有 nullundefined 两种空值,但 JSON 标准只支持 null。当你 JSON.stringify 一个包含 undefined 的对象时,这些值有两种表现:

  • 对象属性值为 undefined → 该属性被跳过
  • 数组元素为 undefined → 转为 null

这个不一致的行为是 JSON.stringify 设计上的历史遗留问题。

实现思路

递归遍历对象树,遇到 undefined 替换为 null,其他值不变。typeof obj === 'object'null 返回 true(typeof null === 'object'),所以需要先判断 obj === null 再判断 typeof obj !== 'object'

ts
if (obj === undefined) return null
if (obj === null || typeof obj !== 'object') return obj

代码中 typeof obj === null 是笔误——应该是 obj === nulltypeof 运算符永远返回字符串,typeof anything === null 永远为 false

另外,这个实现对数组元素的处理依赖于 for...in——for...in 会枚举数组索引,对稀疏数组来说可能跳过空位。Object.valuesfor...of 更可靠。

就地修改 vs 新对象

此实现直接修改原对象,而不是创建新副本。这在一些场景里可能带来额外副作用。如果需要保留原始输入,就要改成返回新对象或新数组的写法。