English 中文(简体)
如何比较地图的关键
原标题:How Javascript compare key of Map

我使用Javascript ES6号特稿,在 no子应用中:

class pairKey {
constructor(x_pos, y_pos) {
    this._X = x_pos;
    this._Y = y_pos;
}

get x() {
    return this._X;
}
set x(x_pos) {
    this._X = x_pos;
}

get y() {
    return this._Y;
}
set y(y_pos) {
    this._Y = y_pos;
}


var allElem = new Map();
allElem.set(new pairKey(1,2),  a );
allElem.set(new pairKey(2,3),  b );

console.log(allElem.has(new pairKey(1,2))); //Should return true instead return false

In this code I want to use a pair of Int as key of my map (allElem).
The problem is that I don t know how Map compare objects in javascript.
Someone can help me?

最佳回答

您的法典之所以失败,是因为地图使用同样的价值算法与钥匙相匹配。 标的与另一个标的具有同等价值,即使两者都具有相同的内在价值(例如,考试、测试<代码>({:1}={a:1})。 - &;这是假的。 你们可以做这项工作的一种方式是,在你们的物体上添加一个关键财产,使同样的内在价值产生同样的钥匙(1至1)。 然后在确定地图条目时使用该钥匙。 例如(Utilizes Symbol.for,以生成可再生钥匙):

 use strict 
class pairKey {
  constructor(x_pos, y_pos) {
    this._X = x_pos;
    this._Y = y_pos;
  }

  get x() {
    return this._X;
  }
  set x(x_pos) {
    this._X = x_pos;
  }

  get y() {
    return this._Y;
  }
  set y(y_pos) {
    this._Y = y_pos;
  }

  get key() {
    return Symbol.for(`pairKey[${this.x}:${this.y}]`);
  }
}
var allElem = new Map();
allElem.set(new pairKey(1, 2).key,  a );
allElem.set(new pairKey(2, 3).key,  b );

console.log(allElem.has(new pairKey(1, 2).key));
问题回答

SameValueZero<=<=>>。 这意味着在物体中使用参考平等,因此,如果您有<条码>a = 新的PairKey (1, 2)和<条码>b = 新的PairKey(1, 2)。 它们不是同一个物体:a != b

因此,你可以做些什么来解决这个问题? 基本有两个解决办法:

  • use not the object itself as a key, but rather a primitive (e.g. string) representation of it, which can be created from distinct instances with the same value
  • use hash consing for your key objects, so that new PairKey always returns the same object if called with the same arguments

Also you might be able to subclass Map where all methods are overwritten so that they handle PairKeys specially, relying on one of the above techniques.

不幸的是,如果提及不力,而且不泄露记忆,便不可能实施洗衣,因此我们必须采用第一种技术:

class Pair {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    toKey() {
        return `Pair(${this.x}, ${this.y})`;
    }
    static key(x, y) {
        return new Pair(x, y).toKey();
    }
}

var allElem = new Map(); // string -> string
allElem.set(Pair.key(1, 2),  a );
allElem.set(Pair.key(2, 3),  b );

console.log(allElem.has(Pair.key(1, 2))); // true

你的地图钥匙是一个目标。 <代码>console.log Returnfalse 由于您重新创建了一个<>新物体,以检索其钥匙。 这确实是同样的问题。 重要的是,它是一个新物体。

如果你想要收回与<代码>新版(1,2)

let key = new pairKey(1,2);
allElem.set(key,  a );

console.log(allElem.has(key));

换言之,如果你把物体用作钥匙,则确保使用同一物体收回价值。

我对提出老问题表示歉意,但我发现了一个非常有趣的解决办法,由以下网站启发:Bergi swer提到,不可能。

class PairKey {
  private static cache: Record<string, PairKey> = {};

  constructor(
    private _x: number, private _y: number,
    action:  create  |  read  |  delete  =  read 
  ) {
      const key = PairKey.key(_x, _y);

      if (action ===  create  || action ===  read ) {
        if (PairKey.cache[key]) {
            return PairKey.cache[key];
        }
        if (action ===  create ) {
          PairKey.cache[key] = this;
        }
      }
      else if (action ===  delete ) {
        delete PairKey.cache[key];
      }
  }

  private static key(x: number, y: number) {
      return `${x}_${y}`;
  }

  get x() {
      return this._x;
  }

  set x(x_pos: number) {
      this._x = x_pos;
  }

  get y() {
      return this._y;
  }

  set y(y_pos: number) {
      this._y = y_pos;
  }
}

const allElem = new Map<PairKey, string>();

allElem.set(new PairKey(1, 2,  create ),  a );  // the action flag to prevent a memory leak

allElem.set(new PairKey(2, 3,  create ),  b );  // the action flag to prevent a memory leak

console.log(allElem.has(new PairKey(1, 2))); // Returns true

allElem.delete(new PairKey(1, 2,  delete ));  // the action flag to prevent a memory leak

console.log(allElem.has(new PairKey(1, 2))); // Returns false

类似解决办法,静态更强:

class PairKey {
  private static cache: Record<string, PairKey> = {};
  private static readonly symbol = Symbol();

  private constructor(private _x: number, private _y: number, symbol: symbol) {
    if (symbol !== PairKey.symbol) {
      throw new Error("Use  PairKey.create()  instead of constructor");
    }
  }

  static create(x: number, y: number) {
    const key = PairKey.key(x, y);

    if (PairKey.cache[key]) {
      return PairKey.cache[key];
    }

    const pairKey = new PairKey(x, y, PairKey.symbol);
    PairKey.cache[key] = pairKey;
    return pairKey;
  }

  static read(x: number, y: number) {
    const key = PairKey.key(x, y);
    return PairKey.cache[key];
  }

  static delete(x: number, y: number) {
    const key = PairKey.key(x, y);
    const pairKey = PairKey.cache[key];
    delete PairKey.cache[key];
    return pairKey;
  }

  private static key(x: number, y: number) {
    return `${x}_${y}`;
  }

  get x() {
    return this._x;
  }

  set x(x_pos: number) {
    this._x = x_pos;
  }

  get y() {
    return this._y;
  }

  set y(y_pos: number) {
    this._y = y_pos;
  }
}

const allElem = new Map<PairKey, string>();

allElem.set(PairKey.create(1, 2),  a );
allElem.set(PairKey.create(2, 3),  b );

console.log(allElem.has(PairKey.read(1, 2))); // Returns true

allElem.delete(PairKey.delete(1, 2));

console.log(allElem.has(PairKey.read(1, 2))); // Returns false




相关问题
selected text in iframe

How to get a selected text inside a iframe. I my page i m having a iframe which is editable true. So how can i get the selected text in that iframe.

How to fire event handlers on the link using javascript

I would like to click a link in my page using javascript. I would like to Fire event handlers on the link without navigating. How can this be done? This has to work both in firefox and Internet ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Clipboard access using Javascript - sans Flash?

Is there a reliable way to access the client machine s clipboard using Javascript? I continue to run into permissions issues when attempting to do this. How does Google Docs do this? Do they use ...

javascript debugging question

I have a large javascript which I didn t write but I need to use it and I m slowely going trough it trying to figure out what does it do and how, I m using alert to print out what it does but now I ...

Parsing date like twitter

I ve made a little forum and I want parse the date on newest posts like twitter, you know "posted 40 minutes ago ","posted 1 hour ago"... What s the best way ? Thanx.