JS Set.has()方法会进行浅层检查吗? [英] Does JS Set.has() method do shallow checks?
问题描述
如果我有一组对象,例如
If I have a set of objects, like
const s = new Set();
s.add({a: 1, b: 2});
s.add({a: 2, b: 2});
我会做
s.has({a: 1, b: 2});
我将获得积极的结果吗? Set
如何处理引用类型?有没有办法告诉它使用自定义检查器/谓词?
Will I have a positive result? How does Set
handle reference types? Is there a way to tell it to use custom checker/predicate?
推荐答案
期望任何本机JavaScript API均通过引用而不是内容(包括浅表比较)来比较对象:
It's expected that any native JavaScript API compare objects by their references and not their contents (including shallow comparison):
({a: 1, b: 2}) !== ({a: 1, b: 2})
Set
isn't an exclusion, it does ===
comparison for every value but NaN
when it looks up values with has
or stores unique values.
这可以通过扩展 Set
并在 has
等方法中使用深度比较来实现,但效率不高.
This could be achieved by extending Set
and using deep comparison in has
, etc. methods but it would be inefficient.
一种更有效的方法是使用 Map
,因为条目应通过规范化的键进行存储和检索,但是应该存储实际的对象.这可以通过使用 JSON.stringify
来完成,但是对象键也应该优先排序,因此第三方实现如
A more efficient way is to use Map
instead, because entries should be stored and retrieved by normalized keys, but actual objects are supposed to be stored. This can be done by using JSON.stringify
, but object keys should be preferable sorted as well, so third-party implementation like json-stable-stringify
may be used.
在这一点上,扩展 Set
或 Map
可能没有太多好处,因为大多数方法都应被覆盖:
At this point there are may be not much benefits from extending either Set
or Map
because most methods should be overridden:
class DeepSet {
constructor (iterable = []) {
this._map = new Map();
for (const v of iterable) {
this.add(v);
}
}
_getNormalizedKey(v) {
// TODO: sort keys
return (v && typeof v === 'object') ? JSON.stringify(v) : v;
}
add(v) {
this._map.set(this._getNormalizedKey(v), v);
return this;
}
has(v) {
return this._map.has(this._getNormalizedKey(v));
}
// etc
}
请注意,此集合仅适用于可以正确序列化为JSON的普通对象.可能还有其他方法可以序列化对象内容,但是没有一种方法可以正确处理所有可能的值,例如符号和类实例.
Notice that this set is intended only for plain objects that can be correctly serialized to JSON. There may be other ways to serialize object contents but none of them will handle all possible values correctly, e.g. symbols and class instances.
这篇关于JS Set.has()方法会进行浅层检查吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!