Appearance
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 有 null 和 undefined 两种空值,但 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 === null。typeof 运算符永远返回字符串,typeof anything === null 永远为 false。
另外,这个实现对数组元素的处理依赖于 for...in——for...in 会枚举数组索引,对稀疏数组来说可能跳过空位。Object.values 或 for...of 更可靠。
就地修改 vs 新对象
此实现直接修改原对象,而不是创建新副本。这在一些场景里可能带来额外副作用。如果需要保留原始输入,就要改成返回新对象或新数组的写法。
