简体   繁体   English

打字稿:在地图中使用日期作为键?

[英]Typescript: using Date as key in Map?

In my application, I need a map of objects per date.在我的应用程序中,我需要每个日期的对象地图。 As typescript has both a Map and a Date objects, I expected this to be as easy as.由于打字稿有一个Map和一个Date对象,我希望这很简单。

  let map: Map<Date, MyObject> = new Map<Date, MyObject>();

And use set to add new keys and values pairs.并使用set添加新的键和值对。 But then I've realized that I cannot get the values using the dates, unless I use the exact same instance of Date .但是后来我意识到我无法使用日期get值,除非我使用完全相同的Date实例。

I've written a unit test with it:我用它写了一个单元测试:

  it('Should not be a problem', () => {
      let d1: Date = new Date(2019, 11, 25);    // Christmas day
      let d2: Date = new Date(2019, 11, 25);    // Same Christmas day?

      let m: Map<Date, string> = new Map<Date, string>();
      m.set(d1, "X");

      expect(m.get(d1)).toBe("X");   // <- This is OK.
      expect(m.get(d2)).toBe("X");   // <- This test fails.
  });

Why is it that I can't get the value from the map unless I use the exact same instance?为什么除非我使用完全相同的实例,否则我无法从地图中获取值?

This is core logic of Map , as you know map stores value in key value pair.这是Map核心逻辑,因为您知道 map 将值存储在键值对中。

For the comparison of keys, the keys should always be of same reference.对于键的比较,键应始终具有相同的引用。 As you might know that string literal references are equal in many programming languages, hence use of string is preferred as key in map.您可能知道字符串字面引用在许多编程语言中是相等的,因此首选使用字符串作为映射中的键。

The above behavior is not only true for date but it is true for any other mutable object type.上述行为不仅适用于date而且适用于任何其他可变对象类型。

eg例如

let str1 = 'test';
let str2 = 'test';
str1 == str2; // true

let str1 = new String('test');
let str2 = new String('test');
str1 == str2; // false

While getting value from map , the keys data is not considered, rather the unique identity of key is search.map获取值时,不考虑键数据,而是键的唯一标识是搜索。 And when you create immutable object each object may have same data but the references of each object will be different.当您创建不可变对象时,每个对象可能具有相同的数据,但每个对象的引用将不同。 Hence it will be treated as different keys.因此它将被视为不同的键。

The solution is use types which can have same references throughout program, such as string literals.解决方案是使用可以在整个程序中具有相同引用的类型,例如字符串文字。

One more example,再举一个例子,

class Demo {
  field: string;
  constructor(f: string) {
    this.field = f;
  }
}

const d1 = new Demo('test');
const d2 = new Demo('test');

// both objects seems same by data, but there references are different
// hence will be treated as separate keys.
const m: Map<any, string> = new Map<any, string>();
m.set(d1, 'value1');

console.log(m.get(d1)); // value1
console.log(m.get(d2)); // undefined

Better use primitive values (number, string) as Map keys:更好地使用原始值(数字、字符串)作为 Map 键:

let m: Map<string, string> = new Map<string, string>();

let d1: Date = new Date(2019, 11, 25);    // Christmas day
let d2: Date = new Date(2019, 11, 25);    // Same Christmas day?

m.set(d1.toDateString(), "X");

console.log(d1.toDateString())
console.log(d2.toDateString())
console.log(m.get(d2.toDateString()))

I provided a link to such behaviour on the above comments.我在上述评论中提供了指向此类行为的链接。

It will always be falsy because those two date objects are distinct mutable javascript objects.它总是错误的,因为这两个日期对象是不同的可变 javascript 对象。

new Date(2019, 11, 25) === new Date(2019, 11, 25) ==> false . new Date(2019, 11, 25) === new Date(2019, 11, 25) ==> false

You can look at answers in this post .您可以在这篇文章中查看答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM