JavaScript中for of与传统for循环解构存Map键致取值undefined的差异问题
核心原因:Map 对引用类型键的判断依据是内存引用身份
Map 匹配键值的规则遵循 SameValueZero 规范:对于字符串、数字这类基本类型,只要值相等就算同一个键;但对于数组、对象这类引用类型,只有两个键指向内存中完全同一个对象时,才会被识别为同一个键——哪怕两个数组的所有元素完全一样,只要是独立创建的两个数组,就会被判定为不同的键。
两段代码的核心差异拆解
getDistances2能正常取值的原因:循环中存入 Map 的键是points[i],这个值就是传入的原始坐标数组的引用——和外部用来取值的coordinates[0]是内存中同一个对象,引用完全一致,自然能匹配到对应的值。代码里的const [x, y] = [...points[i]]操作只是把原数组复制一份、解构读出x、y做距离计算,全程没有用这个复制出来的数组当键,完全不影响键的引用一致性。getDistances1取不到值的原因:循环中存入 Map 的键是[x, y],这是一个每次循环时新建的独立数组。虽然这个新数组的元素值和原坐标数组完全相同,但它是全新的内存对象,和外部coordinates里存储的原数组不是同一个引用,Map自然无法把这个新数组和你传入的原数组判定为同一个键,最后取值就返回undefined。
修正getDistances1的常见写法
在for...of循环中,遍历拿到的当前项本身就是原数组的引用,只需要把解构操作和存键的逻辑拆开,不要手动新建数组当键即可:
function getDistances1(points) { const lookup = new Map(); for (const point of points) { // 解构仅用于计算距离,不用于生成新的键对象 const [x, y] = point; const distance = Math.sqrt(x**2 + y**2); // 直接用遍历拿到的原数组引用当键 lookup.set(point, distance); } return lookup; }
如果你的业务场景需要完全按坐标值匹配键,不依赖数组引用,可以把键换成字符串这类基本类型,比如用
${x},${y}作为键值,这样只要坐标值相同,不管数组是不是同一个引用,都能正常匹配取值。
内容的提问来源于stack exchange,提问作者Woody P Lucas
相关产品推荐
相关产品推荐

