[JSON] Changing the class of an object after its construction

  • Thread starter Thomas 'PointedEars' Lahn
  • Start date
T

Thomas 'PointedEars' Lahn

Raphael Jolivet wrote:

First of all, there are no classes in JavaScript < 2/JScript < 7/ECMAScript
< 4. Those are object-oriented programming languages using prototype-based
inheritance.
obj1 = {
a : 1
b : 2
}

Then, serialized in a string :
"{a : 1, b:2}";

To get the object back (when loading it from prefrences), i do almost :
obj1 = eval("[a:1,b:2");
^^^^^^^^
This will yield a syntax error. Is that why you wrote "almost"?
Ok, my object is now back, but actually, the source object was
a 'myClass' object, with lot of cool methods in it.

What if I want my new object to have all these cool methods ?

You have to add `myClass' into the object's prototype chain.
Right now only `Object' is in its prototype chain as due to
the Object literal, Object() was the constructor implicitly
used.
I've tried
obj1.prototype = new myClass();
But it doesn't work.

"Does not work" is a useless error description. [psf 4.11]

In fact, it MUST NOT work. `obj1' does not refer to a constructor
(i.e. a Function object), so that does not have a `prototype' property.
You are creating one with no intrinsic functionality here.

To make the prototype chain work, you need another prototype.
I found two ways for this:

a)
obj1.__proto__ = new myClass(); // JavaScript only, preserves properties

b)
obj1 = new myClass(); // works everywhere but perhaps resets properties
myClass.call(obj1); // I am not sure about that


HTH

PointedEars
 
T

Thomas 'PointedEars' Lahn

Thomas said:
In fact, it MUST NOT work. `obj1' does not refer to a constructor
(i.e. a Function object), so that does not have a `prototype' property.
You are creating one with no intrinsic functionality here.

To make the prototype chain work, you need another prototype.
I found two ways for this:

a)
obj1.__proto__ = new myClass(); // JavaScript only, preserves properties

or

obj1.__proto__ = myClass.prototype;


PointedEars
 
R

Raphael Jolivet

Hello there,

I have a bunch of objects that I store in a text file (to store
preferences),
after having serialized them with JSON.

Let's say I have my object :

obj1 = {
a : 1
b : 2
}

Then, serialized in a string :
"{a : 1, b:2}";

To get the object back (when loading it from prefrences), i do almost :
obj1 = eval("[a:1,b:2");

Ok, my object is now back, but actually, the source object was
a 'myClass' object, with lot of cool methods in it.

What if I want my new object to have all these cool methods ?
I've tried
obj1.prototype = new myClass();
But it doesn't work.

If I do :
obj1.coolMethod = (new myClass()).coolMethod,
I can get 'coolMethod' working fine.
But I don't want to list all my methods.
This is not nice for maintenance and not nice at all.

Any Idea ?

Thanks in advance,


Raphael
 
V

VK

Raphael said:
Ok, my object is now back, but actually, the source object was
a 'myClass' object, with lot of cool methods in it.

It would help to have more clear picture how of relations between obj1
and myClass before serialization.
JASON's marshalling includes native class methods as well as native
properties - I guess by its description as I did not use it yet too
much.
<http://www.crockford.com/JSON/js.html>

By some problem specifics I can guess that obj1 extends myClass and
inherits "a lot of cool" *static* methods from myClass. Usually
static methods of class-constructor are transient (not serializable)
because it's the opposite way is the best to crash your system on
de-serialization. Just think of objects coming back to you later and
each overriding the static method with its own "timestamped state" of
this method!

This is why right after the de-serialization obj1 is not yet really an
instance of myClass. It's so-called "skeleton": it has everything that
was his own, but it doesn't have yet inherited static members. The
simpliest way to put the flash back on it would be to pass it through
the myClass constructor once over again:

deserialize(obj1);
myClass.apply(obj1);
 
V

VK

VK said:
Raphael Jolivet wrote:
... obj1.prototype ....

My previous post also explain why you should not touch prototype of
neither obj1 nor myClass as it adds / casts *static* members so it
makes the picture more and more chaotoc on each de-serialization.
 
J

John G Harris

Raphael Jolivet said:
Hello there,

I have a bunch of objects that I store in a text file (to store
preferences),
after having serialized them with JSON.

Let's say I have my object :

obj1 = {
a : 1
b : 2
}

Then, serialized in a string :
"{a : 1, b:2}";

To get the object back (when loading it from prefrences), i do almost :
obj1 = eval("[a:1,b:2");

Ok, my object is now back, but actually, the source object was
a 'myClass' object, with lot of cool methods in it.
<snip>

Why not have two constructor functions with their prototype properties
the same.

When you make an object the first time you do
new Thing( <params> );
When you deserialise it you do
new InThing( <string> );

If Thing and InThing do what's needed you won't be able to tell the
difference between the two objects.

John
 
R

Raphael Jolivet

Thanks
"obj1.__proto__ = new myClass()" works well.

I though that "prototype" was a generic property to
manipulate the prototypes of objects, but you're right
It's only for constructors.

__proto___ was what I looked for.


Thanks
 
M

Martin Honnen

Raphael Jolivet wrote:

"obj1.__proto__ = new myClass()" works well.
__proto___ was what I looked for.

But be aware that only the Spidermonkey engine used in Mozilla and
Netscape browsers exposes that __proto__ property, other engines
implementing ECMAScript as the MS JScript engine or the engine used in
Opera do not expose that so using it in script on the web is not cross
browser.
 
R

Rob Williscroft

Raphael Jolivet wrote in in
comp.lang.javascript:
What if I want my new object to have all these cool methods ?
I've tried
obj1.prototype = new myClass();
But it doesn't work.

<script type="text/javascript">
/** Copy an object to a new func()
*/
function copy_json( func, src )
{
var f = function() {}
f.prototype = func.prototype;
var dest = new f();
for ( var i in src ) dest = src;
return dest;
}

/** Sample data
*/
var ob =
{
a : 1, b : 2, c : 3
};

/** Sample type with a prototype method
*/
function MyObject()
{
this.a = this.b = this.c = -1;
return this;
}
MyObject.prototype.upper = function()
{
return "{A:" + this.a + ",B:" + this.b + ",C:" + this.c + "}";
}

/** Does it work
*/
function test()
{
var copy = copy_json( MyObject, ob );

alert( copy.upper() + "\n" + (new MyObject()).upper() );
}
</script>

Rob.
 
R

Raphael Jolivet

But be aware that only the Spidermonkey engine used in Mozilla and
Netscape browsers exposes that __proto__ property, other engines
implementing ECMAScript as the MS JScript engine or the engine used in
Opera do not expose that so using it in script on the web is not cross
browser.

Ok, thanks for the hint.
But my intend is to develop some XUL stuff now. Only Moz/FF/ for now.
AJAX and cross-browser's stuff are way to tricky yet.
 

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
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top