By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,831 Members | 1,031 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,831 IT Pros & Developers. It's quick & easy.

unique reference id

P: n/a

I would like to be able to convert any reference (function, object, or
array) into unique string id and retrieve original reference afterwards
using same id.

The following code does this but only for functions, and for some
unknown reason does not work properly for other kind of references.
var func = function(){};
var ref_id = $GS(func);
// get original reference
var func_2 = $GO(ref_id);
function $GS (ref) { return jsref(ref, "gstr"); }
function $GO (s) { return jsref(s, "gobj"); }
function jsref (ref, what) {

// guess
if (!what) {
what = (typeof(ref) == "string") ? "gobj" : "gstr";
}

var c = jsref;

if (!c.str_ref) c.str_ref = {};
if (!c.ref_str) c.ref_str = {};
if (!c.n) c.n = 0;

if (what == "gstr") {
if (!c.ref_str[ref]) {
c.n++;
c.ref_str[ref] = c.n;
c.str_ref[c.n] = ref;
}
return "jsref:"+ c.ref_str[ref];
}
else if (what == "gobj") {
ref = ref.replace(/\D+/g, '');
return c.str_ref[ref];
}
return null;
}
Oct 14 '08 #1
Share this Question
Share on Google+
17 Replies


P: n/a
Matija Papec schreef:
I would like to be able to convert any reference (function, object, or
array) into unique string id and retrieve original reference afterwards
using same id.

The following code does this but only for functions, and for some
unknown reason does not work properly for other kind of references.
var func = function(){};
var ref_id = $GS(func);
// get original reference
var func_2 = $GO(ref_id);
function $GS (ref) { return jsref(ref, "gstr"); }
function $GO (s) { return jsref(s, "gobj"); }
function jsref (ref, what) {

// guess
if (!what) {
what = (typeof(ref) == "string") ? "gobj" : "gstr";
}

var c = jsref;

if (!c.str_ref) c.str_ref = {};
if (!c.ref_str) c.ref_str = {};
if (!c.n) c.n = 0;

if (what == "gstr") {
if (!c.ref_str[ref]) {
c.n++;
c.ref_str[ref] = c.n;
c.str_ref[c.n] = ref;
}
return "jsref:"+ c.ref_str[ref];
}
else if (what == "gobj") {
ref = ref.replace(/\D+/g, '');
return c.str_ref[ref];
}
return null;
}
Hi,

Just curious: Why don't you simply store the reference itself?

Regards,
Erwin Moller

--
Oct 14 '08 #2

P: n/a
Erwin Moller wrote:
> }
return null;
}

Hi,

Just curious: Why don't you simply store the reference itself?
The reason is ajax.
When making an ajax call, client side is deciding what reference to pass
to server, so client can later operate on the same reference.

Unfortunately references does not survive ajax calls, so there is a need
for unique string representation of reference.
Oct 14 '08 #3

P: n/a
Matija Papec schreef:
Erwin Moller wrote:
>> }
return null;
}
Hi,

Just curious: Why don't you simply store the reference itself?

The reason is ajax.
When making an ajax call, client side is deciding what reference to pass
to server, so client can later operate on the same reference.

Unfortunately references does not survive ajax calls, so there is a need
for unique string representation of reference.
Why don't you make a simple counter (incremental number) and put the
reference as a number in an array or object?
Pass the number via Ajax around, and when the server answer, use the
number to look up the reference.

Regards,
Erwin Moller

--
Oct 14 '08 #4

P: n/a
Erwin Moller schreef:
Matija Papec schreef:
>Erwin Moller wrote:
>>> }
return null;
}
Hi,

Just curious: Why don't you simply store the reference itself?

The reason is ajax.
When making an ajax call, client side is deciding what reference to pass
to server, so client can later operate on the same reference.

Unfortunately references does not survive ajax calls, so there is a need
for unique string representation of reference.

Why don't you make a simple counter (incremental number) and put the
reference as a number in an array or object?
That was poorly phrased.
I mean something like this:

var count=0;
var myRefs = new Array();
function getANumberForThisRef(aRef){
count++;
myRefs[count] = aRef;
}

// do your Ajaxstuff here

function getARefForThisNumber(aNum){
return myRefs[aNum];
}

Regards,
Erwin Moller
Pass the number via Ajax around, and when the server answer, use the
number to look up the reference.

Regards,
Erwin Moller

--
Oct 14 '08 #5

P: n/a
Erwin Moller schreef:
Erwin Moller schreef:
>Matija Papec schreef:
>>Erwin Moller wrote:
}
return null;
}
Hi,

Just curious: Why don't you simply store the reference itself?

The reason is ajax.
When making an ajax call, client side is deciding what reference to pass
to server, so client can later operate on the same reference.

Unfortunately references does not survive ajax calls, so there is a need
for unique string representation of reference.

Why don't you make a simple counter (incremental number) and put the
reference as a number in an array or object?

That was poorly phrased.
I mean something like this:

var count=0;
var myRefs = new Array();
function getANumberForThisRef(aRef){
count++;
myRefs[count] = aRef;
-- return count;
}
/me gets a coffee....

Regards,
Erwin Moller

>
// do your Ajaxstuff here

function getARefForThisNumber(aNum){
return myRefs[aNum];
}

Regards,
Erwin Moller
>Pass the number via Ajax around, and when the server answer, use the
number to look up the reference.

Regards,
Erwin Moller


--
Oct 14 '08 #6

P: n/a
Erwin Moller wrote:
>>Why don't you make a simple counter (incremental number) and put the
reference as a number in an array or object?

That was poorly phrased.
I mean something like this:

var count=0;
var myRefs = new Array();
function getANumberForThisRef(aRef){
count++;
myRefs[count] = aRef;
Yes, I'm already doing this[1], but unfortunately getting same id for
two different objects,
http://www.mcs-informatika.hr/~mcs_matija/js/
[1] I'm also taking care so that the same reference always corresponds
to the same "count" number

>}

/me gets a coffee....
:)

Oct 14 '08 #7

P: n/a
Matija Papec schreef:
Erwin Moller wrote:
>>>Why don't you make a simple counter (incremental number) and put the
reference as a number in an array or object?
That was poorly phrased.
I mean something like this:

var count=0;
var myRefs = new Array();
function getANumberForThisRef(aRef){
count++;
myRefs[count] = aRef;

Yes, I'm already doing this[1], but unfortunately getting same id for
two different objects,
http://www.mcs-informatika.hr/~mcs_matija/js/
[1] I'm also taking care so that the same reference always corresponds
to the same "count" number
Hi,

I checked your code and added some comments after //.
<script>

alert($GS( {foo:1} ));
alert($GS( {bar:2} ));
function $GS (ref) { return jsref(ref, "gstr"); }
function $GO (s) { return jsref(s, "gobj"); }
function jsref (ref, what) {

// guess
if (!what) {
what = (typeof(ref) == "string") ? "gobj" : "gstr";
}

// OK, so here you make c pointing to some reference.
var c = jsref;

if (!c.str_ref) c.str_ref = {};
if (!c.ref_str) c.ref_str = {};
if (!c.n) c.n = 0;

if (what == "gstr") {
if (!c.ref_str[ref]) {
// Here you ADD a property to c, so that is a property for each object.
c.n++;

c.ref_str[ref] = c.n;
c.str_ref[c.n] = ref;
}
return "jsref:"+ c.ref_str[ref];
}
else if (what == "gobj") {
ref = ref.replace(/\D+/g, '');
return c.str_ref[ref];
}
return null;
}
</script>
Conclusion: You are NOT doing what I suggested.
You are adding the n property to your object: poluting your objects with
that, and possibly overwriting existing ones (I cannot tell).

Solution: Review my earlier posted code and use that approach. Use 1
counter for all and don't touch the objects the references point to.

Disclaimer:
Possibly I am missing something since I never use $ in Javascript in the
way you do. I only use $ in regular expressions in JavaScript.
I looked it up in my Definitive Guide 4th edition, but it is not listed
in there in the way you use it.
So maybe I miss something important. ;-)

I have no time right now to investigate the $ futher, but hope my
comments help nonetheless

Regards,
Erwin Moller
>
>>}
/me gets a coffee....

:)

--
Oct 15 '08 #8

P: n/a
Matija Papec wrote:
Erwin Moller wrote:
>>>Why don't you make a simple counter (incremental number) and put the
reference as a number in an array or object?
That was poorly phrased.
I mean something like this:

var count=0;
var myRefs = new Array();
function getANumberForThisRef(aRef){
count++;
myRefs[count] = aRef;

Yes, I'm already doing this[1], but unfortunately getting same id for
two different objects,
That can only be because either you do not test whether you already stored a
reference to the same object, or because there are different objects.
http://www.mcs-informatika.hr/~mcs_matija/js/
q.e.d.

`{x: 1}' and `{x: 1}' (and `[x]' and `[x]') result in references to
*different* objects ({x: 1} != {x: 1}). Each Object (and Array) object
initializer creates a new Object(/Array) object and results in a reference
to it. (In contrast to RegExp object initializers; however, /x/ != /x/ by
definition.)

So what you really want to test is whether two objects have the same
(enumerable) properties and whether those properties have the same value.
One general way to do that:

var equal = true;
for (var p in o1)
{
if (!o2.hasOwnProperty(p) || o2[p] !== o1[p])
{
equal = false;
break;
}
}

for (var p in o2)
{
if (!o1.hasOwnProperty(p) || o1[p] !== o2[p])
{
equal = false;
break;
}
}

Object.prototype.hasOwnProperty() requires an implementation of ECMAScript
Ed. 3. You can achieve greater compatibility but less precision with an
alternative to hasOwnProperty() and, optionally, also with loose comparison
(`!=').

Also note that this needs to be improved for deep compare, and for inherited
enumerable properties.
PointedEars
--
realism: HTML 4.01 Strict
evangelism: XHTML 1.0 Strict
madness: XHTML 1.1 as application/xhtml+xml
-- Bjoern Hoehrmann
Oct 15 '08 #9

P: n/a
Thomas 'PointedEars' Lahn wrote:
>>> myRefs[count] = aRef;
Yes, I'm already doing this[1], but unfortunately getting same id for
two different objects,

That can only be because either you do not test whether you already stored a
reference to the same object, or because there are different objects.
>http://www.mcs-informatika.hr/~mcs_matija/js/

q.e.d.

`{x: 1}' and `{x: 1}' (and `[x]' and `[x]') result in references to
*different* objects ({x: 1} != {x: 1}).
Yes, of course they refer to different objects and I'm expecting such
behavior.
In the mean time I found what was the problem when looking for object id
in lookup table.
var h1 = {foo: 33};
var h2 = {foo: 33};
// false as expected
alert(h1==h2);
var lookup = {};
lookup[h1] = true;
// true, but I'm expecting false or undefined
alert(lookup[h2]);

It seems that references cannot be used as *object keys* so lookup fails
when searching for reference.

>Each Object (and Array) object
initializer creates a new Object(/Array) object and results in a reference
to it. (In contrast to RegExp object initializers; however, /x/ != /x/ by
definition.)

So what you really want to test is whether two objects have the same
(enumerable) properties and whether those properties have the same value.
One general way to do that:
Yes, that would be solution for comparing object properties.
tnx
Oct 17 '08 #10

P: n/a
Erwin Moller wrote:
// OK, so here you make c pointing to some reference.
var c = jsref;

if (!c.str_ref) c.str_ref = {};
if (!c.ref_str) c.ref_str = {};
if (!c.n) c.n = 0;

if (what == "gstr") {
if (!c.ref_str[ref]) {
// Here you ADD a property to c, so that is a property for each object.
c.n++;

c.ref_str[ref] = c.n;
c.str_ref[c.n] = ref;
}
return "jsref:"+ c.ref_str[ref];
}
else if (what == "gobj") {
ref = ref.replace(/\D+/g, '');
return c.str_ref[ref];
}
return null;
}
</script>
Conclusion: You are NOT doing what I suggested.
You are adding the n property to your object: poluting your objects with
that, and possibly overwriting existing ones (I cannot tell).
c is actually referring to jsref function (or "this"), so
c.str_ref,
c.ref_str and
c.n
are class properties.

First two are lookup objects (or hashes) and c.n is counter for unique
reference id's.

Solution: Review my earlier posted code and use that approach. Use 1
counter for all and don't touch the objects the references point to.

Disclaimer:
Possibly I am missing something since I never use $ in Javascript in the
way you do. I only use $ in regular expressions in JavaScript.
I looked it up in my Definitive Guide 4th edition, but it is not listed
in there in the way you use it.
So maybe I miss something important. ;-)
There is nothing special with '$', I was just carried away after playing
with jQuery :)
I have no time right now to investigate the $ futher, but hope my
comments help nonetheless
tnx for hints.

Oct 17 '08 #11

P: n/a
On Oct 17, 10:53 am, Matija Papec wrote:
Thomas 'PointedEars' Lahn wrote:
<snip>
>`{x: 1}' and `{x: 1}' (and `[x]' and `[x]') result in references
to *different* objects ({x: 1} != {x: 1}).

Yes, of course they refer to different objects and I'm expecting
such behavior.
In the mean time I found what was the problem when looking for
object id in lookup table.

var h1 = {foo: 33};
var h2 = {foo: 33};
// false as expected
alert(h1==h2);

var lookup = {};
lookup[h1] = true;
// true, but I'm expecting false or undefined
alert(lookup[h2]);

It seems that references cannot be used as *object keys*
One of consequences of attaching arbitrary terminology to aspects of
javascript is that it tends to introduce unsound expectations. There
are no "object keys", they are property names. And being names it
should not be too surprising if they are constrained to being
sequences of zero or more (Unicode) characters.
so lookup fails
when searching for reference.
<snip>
Bracket notation property accessors type-convert the value of the
expression that appears between the brackets into a string. When the
value of the expression is an object that type-conversion is (almost
always) the result of calling the - toString - method of the object,
which is usually the one inherited from the - Object.prototype - (at
least for Object objects (as opposed to functions, regular
expressions, arrays, etc.)). For your two objects the results of
calling their - toString - methods are identical so they both end up
referring to the same property name.

Richard.
Oct 17 '08 #12

P: n/a
Matija Papec schreef:
Erwin Moller wrote:
>// OK, so here you make c pointing to some reference.
var c = jsref;

if (!c.str_ref) c.str_ref = {};
if (!c.ref_str) c.ref_str = {};
if (!c.n) c.n = 0;

if (what == "gstr") {
if (!c.ref_str[ref]) {
// Here you ADD a property to c, so that is a property for each object.
c.n++;

c.ref_str[ref] = c.n;
c.str_ref[c.n] = ref;
}
return "jsref:"+ c.ref_str[ref];
}
else if (what == "gobj") {
ref = ref.replace(/\D+/g, '');
return c.str_ref[ref];
}
return null;
}
</script>
Conclusion: You are NOT doing what I suggested.
You are adding the n property to your object: poluting your objects with
that, and possibly overwriting existing ones (I cannot tell).

c is actually referring to jsref function (or "this"), so
c.str_ref,
c.ref_str and
c.n
are class properties.
Oops sorry.
As you can tell I don't program JavaScript at all in the way you do it.

Erwin Moller <-- Old fashioned guy who likes all his functions named. ;-)

However, I am totally sure my posted approach will work, since I used a
similar approach once (including the Ajax calls) without any problems.

So if you just ditch all the fancy stuff I don't get, you'll have
yourself a working reference-passing-getting thingy, ready for use to
pass around the id to ajax and back. :P

Good luck.

Regards,
Erwin Moller
Oct 17 '08 #13

P: n/a
Matija Papec wrote:
var h1 = {foo: 33};
var h2 = {foo: 33};
// false as expected
alert(h1==h2);

var lookup = {};
lookup[h1] = true;
// true, but I'm expecting false or undefined
alert(lookup[h2]);
A possibility to make that work is to serialize the object when converted
into a string for property lookup, using the aforementioned iteration
algorithm in its toString() method or explicitly calling a serializer method
on property access:

function serialize(o)
{
var a = [{];

for (var p in o)
{
a.push(...)
}

return a.join(",") + "}";
}

However, of course that does not allow to differentiate between different
objects, just between objects with different enumerable properties. A
solution for the former, though, is to store object references as elements
of an array, or (more efficient on retrieval) to store references to objects
as elements of an array that is referred to by a property of another object
which name is a serialization of the object to be stored (a hash table
algorithm):

var registry = {
items: {},
add: function(o) {
var it = this.items;
var s = serialize(o);
if (!it.hasOwnProperty(s))
{
it[s] = [o];
}
else
{
var a = it[s];
if (a.indexOf(o) < 0) a.push(o);
}
}
};

Note that Array.prototype.indexOf() is a proprietary method available in
JavaScript since version 1.6; you need a fallback for other implementations.
There are also caveats for other language features used here.

<http://PointedEars.de/scripts/es-matrix/>
PointedEars
--
var bugRiddenCrashPronePieceOfJunk = (
navigator.userAgent.indexOf('MSIE 5') != -1
&& navigator.userAgent.indexOf('Mac') != -1
) // Plone, register_function.js:16
Oct 17 '08 #14

P: n/a
Thomas 'PointedEars' Lahn wrote:
* function serialize(o)
* {
* * var a = [{];
var a = ["{"];
* * for (var p in o)
* * {
* * * a.push(...)
Trailing semicolon not required, but good style and missing here.
* * }

* * return a.join(",") + "}";
* }
[...]
* var registry = {
* * items: {},
* * add: function(o) {
* * * var it = this.items;
* * * var s = serialize(o);
* * * if (!it.hasOwnProperty(s))
* * * {
* * * * it[s] = [o];
* * * }
* * * else
* * * {
* * * * var a = it[s];
* * * * if (a.indexOf(o) < 0) a.push(o);
* * * }
* * }
* };
Reviewing this, it only works with objects that never change, though.
Anyhow, maybe the hash table algorithm helps someone somewhere else.
PointedEars
Oct 20 '08 #15

P: n/a
Thomas 'PointedEars' Lahn wrote:
function serialize(o)
{
var a = [{];

for (var p in o)
{
a.push(...)
}

return a.join(",") + "}";
}

However, of course that does not allow to differentiate between different
objects, just between objects with different enumerable properties. A
solution for the former, though, is to store object references as elements
of an array, or (more efficient on retrieval) to store references to objects
as elements of an array that is referred to by a property of another object
which name is a serialization of the object to be stored (a hash table
algorithm):
I think I'll stick with plain array for lookups as there are not many
references to be stored and it will not suffer from serialization
overhead (in case if there is any). Tnx for the tips!

Oct 21 '08 #16

P: n/a
Erwin Moller wrote:
>c is actually referring to jsref function (or "this"), so
c.str_ref,
c.ref_str and
c.n
are class properties.

Oops sorry.
As you can tell I don't program JavaScript at all in the way you do it.

Erwin Moller <-- Old fashioned guy who likes all his functions named. ;-)

However, I am totally sure my posted approach will work, since I used a
similar approach once (including the Ajax calls) without any problems.

So if you just ditch all the fancy stuff I don't get, you'll have
yourself a working reference-passing-getting thingy, ready for use to
pass around the id to ajax and back. :P
I'm working on new version which will use some of your approach. :)

Oct 21 '08 #17

P: n/a
Richard Cornford wrote:
>when searching for reference.
<snip>
Bracket notation property accessors type-convert the value of the
expression that appears between the brackets into a string. When the
value of the expression is an object that type-conversion is (almost
always) the result of calling the - toString - method of the object,
which is usually the one inherited from the - Object.prototype - (at
least for Object objects (as opposed to functions, regular
expressions, arrays, etc.)). For your two objects the results of
calling their - toString - methods are identical so they both end up
referring to the same property name.
Tnx for clarification.
To be honest, I've expected something similar to perl behavior when
dealing with references

perl -e 'print {}'
HASH(0x817f880)

:)
Oct 21 '08 #18

This discussion thread is closed

Replies have been disabled for this discussion.