You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Set.Has()无法处理数组?如何用不可变类型存储坐标并高效查询

用不可变类型存储坐标适配Set的方案

原因分析

Set 判断元素是否存在采用 SameValueZero 算法:对于引用类型(比如数组),只有当两个值是同一个引用时才会被视为相等。所以即使 [1,2] 和另一个 [1,2] 内容完全一致,它们是不同的数组实例,Set.has() 会返回 false。

方案1:使用 TC39 实验性的 Tuple 类型

TC39 的 Tuple 提案定义了不可变的有序值集合,内容相同的元组会被视为相等(类似字符串、数字等基本类型的比较逻辑),完美适配 Set 的存在性检查。

用法示例

// 注意:目前属于实验性特性,需在支持的环境开启(比如 Chrome 启用 Experimental JavaScript 特性)
const coordinateSet = new Set();
// 用 #[...] 创建元组
const coord1 = #[1, 2];
const coord2 = #[1, 2];

coordinateSet.add(coord1);
console.log(coordinateSet.has(coord2)); // 输出 true

元组的核心特性:

  • 不可变性:无法修改元组内的元素
  • 值语义:内容相同则视为相等,而非引用相同

方案2:自定义不可变坐标类 + 享元模式

如果无法使用实验性特性,可以自定义一个不可变的坐标类,通过享元模式确保相同坐标复用同一个实例,让 Set 能正确识别重复元素。

实现示例

class ImmutableCoordinate {
  constructor(x, y) {
    // 锁定属性,确保不可修改
    Object.defineProperty(this, 'x', { value: x, writable: false });
    Object.defineProperty(this, 'y', { value: y, writable: false });
  }

  // 静态缓存池,复用相同坐标的实例
  static _cache = new Map();

  static create(x, y) {
    const key = `${x},${y}`;
    if (!this._cache.has(key)) {
      this._cache.set(key, new ImmutableCoordinate(x, y));
    }
    return this._cache.get(key);
  }
}

// 使用方式
const coordinateSet = new Set();
const coordA = ImmutableCoordinate.create(1, 2);
const coordB = ImmutableCoordinate.create(1, 2);

coordinateSet.add(coordA);
console.log(coordinateSet.has(coordB)); // 输出 true

这种方式既保证了坐标的不可变性,又通过实例复用让 Set 能正确判断元素是否存在。

方案3:Object.freeze 冻结数组(局限性较大)

用 Object.freeze() 可以冻结数组使其不可变,但不同实例的引用依然不同,Set 会视为不同元素。只有始终复用同一个冻结数组实例时才生效:

const coord = Object.freeze([1, 2]);
const coordinateSet = new Set([coord]);

console.log(coordinateSet.has(coord)); // true
console.log(coordinateSet.has(Object.freeze([1, 2]))); // false(不同引用)

这种方式仅适用于固定坐标的场景,不推荐动态创建坐标时使用。

内容的提问来源于stack exchange,提问作者Cincinnatus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 00:11:00