如何将JSON内字符串形式的函数转为JS对象函数属性
核心结论
- 该需求完全可实现
- 可以不使用
eval完成转换 - 原生
JSON.parse/JSON.stringify不支持函数类型是符合标准的:JSON规范本身只支持字符串、数字、布尔值、null、对象、数组这几类数据类型,函数不属于标准JSON支持的类型,所以序列化时会被自动忽略,反序列化时也不会自动把字符串解析为函数。
无eval实现方案
你存储的函数本质是符合JS语法的字符串,使用new Function构造器即可完成字符串到函数对象的转换,不需要调用eval,且相比eval作用域更可控、安全风险更低。
完整实现代码如下:
// 原始JSON字符串 const jsonStr = `{"obj":{ "a": "abc", "b": "(v) => { console.log('Hi', v) }" }}`; // 第一步:先做标准JSON解析,得到基础对象 const rawParsed = JSON.parse(jsonStr); /** * 递归转换对象中符合规则的函数字符串为真实函数 * @param {any} value 待处理的值 * @returns 处理后的值 */ const convertFunctionField = (value) => { // 非对象类型直接判断是否需要转函数 if (typeof value !== 'object' || value === null) { if (typeof value !== 'string') return value; // 匹配规则:判断字符串是否为箭头函数/普通函数格式,可根据业务约定调整匹配规则 const isFunctionSyntax = /^\s*(\([^)]*\)|[a-zA-Z_$][\w$]*)\s*=>|^\s*function\s*\(/.test(value); if (!isFunctionSyntax) return value; // 用new Function还原函数,全程不使用eval return new Function(`return ${value}`)(); } // 对象类型递归处理每个属性 for (const key of Object.keys(value)) { value[key] = convertFunctionField(value[key]); } return value; }; // 执行转换,得到最终目标对象 const converted = convertFunctionField(rawParsed); const obj = converted.obj; // 验证结果 console.log(typeof obj.a); // 输出 string console.log(typeof obj.b); // 输出 function,符合预期
只要你不主动调用obj.b(),函数内部的代码永远不会执行,完全满足“仅构造目标JS对象、不实际执行转换得到的函数”的要求。
注意事项
- 不存在完全不使用动态代码解析能力,就能把字符串转成JS函数对象的方案。如果你完全禁止
eval、new Function这类动态代码构造能力,就无法把字符串转成原生函数属性,只能保留字符串格式。 - 上述方案中
new Function生成的函数默认运行在全局作用域,无法访问转换逻辑所在块级作用域的局部变量,相比直接执行eval的作用域污染、代码注入风险要低很多。 - 请务必做好函数字符串的格式校验,严格约定哪些字段、哪些格式的字符串需要被转换为函数,避免把普通文本(尤其是用户输入的不可信内容)误转为函数,引发安全问题。
内容的提问来源于stack exchange,提问作者kartik gavara
相关产品推荐
相关产品推荐

