Vue2升级Vue3后无法为对象分配JavaScript函数问题求助
循环中创建的函数无法赋值给对象?其实是JSON序列化的锅
近期把Vue2项目升级到Vue3,同时将Node版本从v10.15.3-x64升级到v18.16.0-x64,遇到一个奇怪的问题:循环里创建的函数bar能在循环内调用,也能通过外部变量ff调用,但赋值给api_calls对象后,用JSON.stringify打印时看不到函数,甚至直接打印api_calls[name]显示undefined。
代码示例
export function generate_api_calls(app_name) { let api_calls = {} api_calls['cameraFeed'] = `http://${hostname}:${camera_port}${CAMERA_FEED_URL}` let ff let items = [1, 2, 3, 4] for (let i in items) { let name = items[i] function bar(j) { logger.info(`bar ${j}`) }; bar(i) ff = bar api_calls[name] = bar; logger.info(`generate_api_calls api ${name} ${JSON.stringify(api_calls)}`) logger.info(`generate_api_calls api ${JSON.stringify(api_calls[name])}`) } ff('00'); logger.info(`generate_api_calls 5 ${JSON.stringify(api_calls)}`) return api_calls }
运行日志
2023-05-30_17:39:24.582-gui.vue.app-INFO: bar 0 2023-05-30_17:39:24.582-gui.vue.app-INFO: generate_api_calls api 1 {"cameraFeed":"http://localhost:5051/camera/feed"} 2023-05-30_17:39:24.583-gui.vue.app-INFO: generate_api_calls api undefined 2023-05-30_17:39:24.583-gui.vue.app-INFO: bar 1 2023-05-30_17:39:24.584-gui.vue.app-INFO: generate_api_calls api 2 {"cameraFeed":"http://localhost:5051/camera/feed"} 2023-05-30_17:39:24.584-gui.vue.app-INFO: generate_api_calls api undefined 2023-05-30_17:39:24.585-gui.vue.app-INFO: bar 2 2023-05-30_17:39:24.585-gui.vue.app-INFO: generate_api_calls api 3 {"cameraFeed":"http://localhost:5051/camera/feed"} 2023-05-30_17:39:24.586-gui.vue.app-INFO: generate_api_calls api undefined 2023-05-30_17:39:24.586-gui.vue.app-INFO: bar 3 2023-05-30_17:39:24.587-gui.vue.app-INFO: generate_api_calls api 4 {"cameraFeed":"http://localhost:5051/camera/feed"} 2023-05-30_17:39:24.587-gui.vue.app-INFO: generate_api_calls api undefined 2023-05-30_17:39:24.588-gui.vue.app-INFO: bar 00 2023-05-30_17:39:24.588-gui.vue.app-INFO: generate_api_calls 5 {"cameraFeed":"http://localhost:5051/camera/feed"}
核心原因
JSON的规范只允许序列化原始值(字符串、数字、布尔、null)、对象和数组,函数不属于可序列化的内容。所以:
- 用
JSON.stringify(api_calls)时,所有函数类型的属性会被直接忽略,导致日志里看不到; - 用
JSON.stringify(api_calls[name])时,传入的是函数,会直接返回undefined,这就是日志显示undefined的原因。
但实际上,函数已经成功赋值给api_calls对象——你能通过ff调用函数,说明bar本身是有效的,只是日志打印方式不对,让你误以为没赋值成功。
验证与解决方法
- 换打印方式验证:不要用
JSON.stringify,直接打印对象或函数本身:// 直接打印对象(Node环境会显示函数) logger.info(`generate_api_calls api ${name}`, api_calls) // 打印函数的文本内容 logger.info(`generate_api_calls api ${api_calls[name].toString()}`) - 直接调用函数验证:在循环里添加
api_calls[name](i),看是否能正常输出日志,确认函数已赋值。 - 循环写法优化:遍历数组更推荐用
for...of或forEach,避免for...in可能的索引问题:items.forEach((name, i) => { function bar(j) { logger.info(`bar ${j}`) } bar(i) ff = bar api_calls[name] = bar // 验证调用 api_calls[name](i) })
内容的提问来源于stack exchange,提问作者mitch
相关产品推荐
相关产品推荐

