JavaScript中const声明的常量字典在函数内被意外修改如何解决
问题原因
const在JavaScript中仅保证变量的引用地址不可重新赋值,无法限制对象、数组这类引用类型内部的属性/成员被修改,你的代码直接对原始存储的坐标数组做了写入操作,是导致TheGraph数据被篡改的核心原因:
- 遍历路径节点时,你通过
var point = TheGraph[...].Coordinates直接拿到了TheGraph中存储的原始坐标数组的引用,后续执行point[0] = xxx、point[1] = xxx的赋值操作,会直接修改原始数组内存储的值。 - 后续处理终点房间坐标时,同样直接取出
Rooms中存储的原始坐标数组修改,也会篡改Rooms的原始数据。 - 额外逻辑bug:你调用
possRoutes.reduce()筛选最短路径时没有接收返回值,代码始终使用possRoutes[0]作为绘制路径,最短路径计算逻辑完全没有生效。
修复方案
- 所有需要对原始坐标做转换计算的场景,先创建坐标副本再操作,不要直接修改原始数组:
替换路径遍历部分的坐标获取逻辑:
替换终点坐标的获取逻辑:// 原来的错误写法 // var point = TheGraph[point = possRoutes[0].path[cor]].Coordinates // 修复:先取原始值,再创建副本 const nodeKey = shortest.path[cor] const rawCoord = TheGraph[nodeKey].Coordinates const point = [rawCoord[0], rawCoord[1]] // 创建新数组,不影响原数据// 原来的错误写法 // point = Rooms[heading][0] // 修复:拷贝原始坐标 const rawRoomCoord = Rooms[heading][0] const point = [rawRoomCoord[0], rawRoomCoord[1]] - 接收
reduce的返回值,让最短路径筛选逻辑生效:// 原来的写法没有接收返回值 // possRoutes.reduce(...) const shortest = possRoutes.reduce(function(prev, curr) { return prev.distance < curr.distance ? prev : curr; }); // 后续遍历路径时遍历shortest.path即可 - (可选)如果需要从根源避免原始数据被误修改,可以递归冻结
TheGraph对象,一旦有代码尝试修改内部值会直接报错,方便提前定位问题:function deepFreeze(obj) { Object.keys(obj).forEach(key => { if (typeof obj[key] === 'object' && obj[key] !== null) deepFreeze(obj[key]) }) return Object.freeze(obj) } // 定义完TheGraph之后执行冻结 deepFreeze(TheGraph)
内容的提问来源于stack exchange,提问作者radG3
相关产品推荐
相关产品推荐

