JavaScript加载游戏数据时如何保留数组内的对象引用?
问题本质
你遇到的引用断开问题,根源是JSON.parse()会生成全新的对象树,读档时直接执行gameData = loadData会让gameData指向新的对象树,而全局声明的farm、hut还是指向初始化时创建的旧对象,两者完全脱离关联,自然不会同步更新。
初始化时farm === gameData.buildingArray[0]为真,读档后该判断为假,就是引用断开的直接证明。
方案1:最小改动修复(无需调整现有业务代码)
不需要修改其他逻辑,仅调整loadGame的实现:
- 不要直接替换整个
gameData对象,而是把存档数据覆写到原有gameData对象上,保留原对象的引用地址 - 手动把全局的
farm、hut重新指向gameData.buildingArray里的对应元素,恢复引用关联
修改后的loadGame代码:
function loadGame() { const savedData = localStorage.getItem(localStorageName) if (!savedData) return const loadData = JSON.parse(savedData) // 把存档数据覆写到原gameData对象,不替换引用 Object.assign(gameData, loadData) // 恢复全局变量和数组元素的引用关联 farm = gameData.buildingArray[0] hut = gameData.buildingArray[1] console.log("Data Loaded") }
方案2:架构重构(更易维护,从根源避免引用问题)
你单独声明全局建筑变量是为了调用方便,但散放的全局变量很容易出现引用不同步的问题,建议把所有游戏状态收敛到gameData单一根节点下:
// 所有建筑数据统一放在gameData下,不单独声明全局变量 const gameData = { // 用对象存储建筑,方便按名称直接访问 buildings: { farm: { amount: 0 }, hut: { amount: 0 } }, // 如果需要数组格式做遍历,用getter动态生成,永远和对象数据同步 get buildingArray() { return Object.values(this.buildings) } } // 存读档逻辑 function saveGame() { localStorage.setItem(localStorageName, JSON.stringify(gameData)) console.log("Data Saved") } function loadGame() { const savedData = localStorage.getItem(localStorageName) if (savedData) { const loadData = JSON.parse(savedData) Object.assign(gameData, loadData) console.log("Data Loaded") } }
后续访问建筑属性直接用gameData.buildings.farm.amount即可,可读性和维护性都更高,新增建筑时只需要在gameData.buildings里添加对应项,不需要手动维护buildingArray,也不会再出现引用不同步的问题。
注意事项
如果后续建筑类型增多,不要用数组下标对应建筑类型,建议给每个建筑添加唯一的type字段做标识,避免数组顺序调整后出现数据错位的问题。
内容的提问来源于stack exchange,提问作者Carcanken
相关产品推荐
相关产品推荐

