JavaScript JSON 深层字符串替换:replaceAll 与递归遍历

常见写法

e = JSON.parse(
    JSON.stringify(e).replace(
        /https:\/\/old-domain\.obs\.cn-east-4\.example\.com:443/g,
        '/api'
    )
);

先序列化为 JSON 字符串,全局替换目标子串,再反序列化回对象。适合简单的 URL 替换场景。

用 replaceAll 替代正则

对字面字符串使用正则容易漏掉 . 的转义(.com 写成 .com 会匹配任意字符),直接用 replaceAll 更安全:

const target = 'https://old-domain.obs.cn-east-4.example.com:443';

e = JSON.parse(
    JSON.stringify(e).replaceAll(target, '/api')
);

replaceAll 是纯字符串匹配,不会误伤相邻字符,可读性也更强。

JSON.stringify 会丢失特殊值

// 以下类型经 JSON.stringify 后会丢失或变形
new Date()   // 变为 ISO 字符串,失去 Date 类型
new Map()    // 变为 {}
new Set()    // 变为 {}
undefined    // 对象属性被整体删除
BigInt       // 抛出 TypeError
function     // 被删除

如果对象中包含这些类型,序列化 + 替换 + 反序列化会静默丢失数据。

推荐:递归遍历替换

function deepReplace(obj, from, to) {
    if (typeof obj === 'string') {
        return obj.replaceAll(from, to);
    }

    if (Array.isArray(obj)) {
        return obj.map(v => deepReplace(v, from, to));
    }

    if (obj && typeof obj === 'object') {
        for (const k in obj) {
            obj[k] = deepReplace(obj[k], from, to);
        }
    }

    return obj;
}

deepReplace(e, 'https://old-domain.com', '/api');

不走序列化路径,Date / Map / Set / 原型链全部保留,也适合在 hook 网络返回数据时做在线 URL 替换。

适用场景对比

场景推荐方式
简单纯字符串对象JSON.parse(JSON.stringify(e).replaceAll(...))
含 Date / Map / Set 的对象deepReplace() 递归遍历
只替换字面字符串(无转义歧义)replaceAll 替代正则
hook 网络数据在线修改deepReplace()