admin管理员组文章数量:1302384
I have a function that receives a list of JS objects as an argument. I need to store information about those objects in a private variable for future reference. I do not want to stuff a property into the objects themselves, I just want to keep it out of band in a dictionary. I need to be able to lookup metadata for an object in sub-linear time.
For this I need a hash
function such that, for any two objects o1
and o2
,
hash(o1) !== hash(o2)
whenever o1 !== o2
.
A perfect example of such a hash function would be the memory address of the object, but I don't think JS exposes that. Is there a way?
I have a function that receives a list of JS objects as an argument. I need to store information about those objects in a private variable for future reference. I do not want to stuff a property into the objects themselves, I just want to keep it out of band in a dictionary. I need to be able to lookup metadata for an object in sub-linear time.
For this I need a hash
function such that, for any two objects o1
and o2
,
hash(o1) !== hash(o2)
whenever o1 !== o2
.
A perfect example of such a hash function would be the memory address of the object, but I don't think JS exposes that. Is there a way?
Share edited Jan 24, 2014 at 21:35 masonk asked Jan 24, 2014 at 21:24 masonkmasonk 9,7982 gold badges49 silver badges60 bronze badges 9-
1
You can check for reference equality directly
o1 === o2
– Benjamin Gruenbaum Commented Jan 24, 2014 at 21:25 -
1
In JS the expression
{} === {}
evaluates tofalse
. Do you expect{}
and{}
to hash to the same value? – Matt Ball Commented Jan 24, 2014 at 21:27 - 2 The Google Closure library just adds a unique property to an object: docs.closure-library.googlecode./git/…. – Felix Kling Commented Jan 24, 2014 at 21:28
-
1
@masonk Then store the objects themselves and use
===
. It won't be fast, but I don't think you can do better without touching the objects. – John Dvorak Commented Jan 24, 2014 at 21:31 -
1
When jQuery attempts to solve this problem for
.data()
, it adds one unique string property to the source object that serves as the lookup key in a dictionary. Then, if someone give you the source object, you can retrieve the lookup key and then look that up in your dictionary to get the parallel data. The object reference itself cannot be stringified to be unique so you can't use that as a key. – jfriend00 Commented Jan 24, 2014 at 21:43
4 Answers
Reset to default 2Each object reference is different. Why not push the object onto an array? Traversing the array looking for an object reference might still perform better than inspecting each object in a recursive manor to generate a hash key.
function Dictionary() {
var values = [];
function contains(x) {
var i = values.length;
while(i--) {
if (values[i] === x) {
return true;
}
}
return false;
}
function count() {
return values.length;
}
function get(i) {
return (i >= 0 && i < values.length) ? values[i] : null;
}
function set(o) {
if (contains(o)) {
throw new Error("Object already exists in the Dictionary");
}
else {
return values.push(o) - 1;
}
}
function forEach(callback, context) {
for (var i = 0, length = values.length; i < length; i++) {
if (callback.call(context, values[i], i, values) === false) {
break;
}
}
}
return {
get: get,
set: set,
contains: contains,
forEach: forEach,
count: count
};
}
And to use it:
var objects = Dictionary();
var key = objects.set({});
var o = objects.get(key);
objects.contains(key); // returns true
objects.forEach(function(obj, key, values) {
// do stuff
}, this);
objects.count(); // returns 1
objects.set(o); // throws an error
To store metadata about objects, you can use an WeakMap:
WeakMaps are key/value maps in which keys are objects.
Note that this API is still experimental and thus not widely supported yet (see support table). There is a polyfill implementation which makes use of defineProperty
to set GUIDs (see details here).
Javascript does not provide direct access to memory (or to the file system for that matter).
You'd probably just want to create your properties/variables within the analysis (hash) function, and then return them to where the function was called from to be stored/persisted for later reference.
Thanks everyone who chipped in to reply. You all have convinced me that what I want to do is currently not possible in JavaScript.
There seem to be two basic promises that someone with this use case can chose between:
Linear search using
===
===
appears to be the only built-in way to distinguish between two identically-valued objects that have different references. (If you had two objects,o1
ando2
, and did a deep parison and discovered that they were value-identical, you might still want to know if they're reference-identical. Besides===
you could do something weird like add a property too1
and see if showed up ino2
).Add a property to the object.
I didn't like this approach because there's no good reason why I should have to expose this information to the outside world. However, a colleague tipped me off to a feature that I didn't know about: Object.defineProperty. With this, I can alleviate my main concerns: first, that my id would show up, unwanted, during object enumeration, and second, that someone could inadvertently alter my id if there were to be a namespace collision.
So, in case anyone es here wanting the same thing I wanted, I'm putting it up there for the record that I'm going to add a unique id using Object.defineProperty.
本文标签: hashHashing JavaScript objectsStack Overflow
版权声明:本文标题:hash - Hashing JavaScript objects - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741711866a2393891.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论