unique reference id

M

Matija Papec

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;
}
 
E

Erwin Moller

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

--
 
M

Matija Papec

Erwin said:
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.
 
E

Erwin Moller

Matija Papec schreef:
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

--
 
E

Erwin Moller

Erwin Moller schreef:
Matija Papec schreef:

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


--
 
E

Erwin Moller

Erwin Moller schreef:
Erwin Moller schreef:
Matija Papec schreef:

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


--
 
M

Matija Papec

Erwin said:
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....

:)
 
E

Erwin Moller

Matija Papec schreef:
Erwin said:
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


--
 
T

Thomas 'PointedEars' Lahn

Matija said:
Erwin said:
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.

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
 
M

Matija Papec

Thomas said:
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.

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
 
M

Matija Papec

Erwin said:
// 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.
 
R

Richard Cornford

Thomas 'PointedEars' Lahn wrote:
`{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.
 
E

Erwin Moller

Matija Papec schreef:
Erwin said:
// 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
 
T

Thomas 'PointedEars' Lahn

Matija said:
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 = [o];
}
else
{
var a = it;
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
 
T

Thomas 'PointedEars' Lahn

Thomas said:
  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 = [o];
      }
      else
      {
        var a = it;
        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
 
M

Matija Papec

Thomas said:
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!
 
M

Matija Papec

Erwin said:
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. :)
 
M

Matija Papec

Richard said:
<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)

:)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,138
Messages
2,570,802
Members
47,348
Latest member
nethues

Latest Threads

Top