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

Discussion in 'Javascript' started by Thomas 'PointedEars' Lahn, Nov 20, 2005.

  1. 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
     
    Thomas 'PointedEars' Lahn, Nov 20, 2005
    #1
    1. Advertising

  2. Thomas 'PointedEars' Lahn wrote:

    > 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
     
    Thomas 'PointedEars' Lahn, Nov 20, 2005
    #2
    1. Advertising

  3. 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
     
    Raphael Jolivet, Nov 20, 2005
    #3
  4. Thomas 'PointedEars' Lahn

    VK Guest

    Re: Changing the class of an object after its construction

    Raphael Jolivet wrote:
    > 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);
     
    VK, Nov 20, 2005
    #4
  5. Thomas 'PointedEars' Lahn

    VK Guest

    Re: Changing the class of an object after its construction

    VK wrote:
    > 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.
     
    VK, Nov 20, 2005
    #5
  6. In article <ux%ff.1569$>, Raphael Jolivet
    <> writes
    >
    >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
    --
    John Harris
     
    John G Harris, Nov 20, 2005
    #6
  7. 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

    > Thomas 'PointedEars' Lahn wrote:
    >
    >
    >>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
     
    Raphael Jolivet, Nov 20, 2005
    #7
  8. 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.


    --

    Martin Honnen
    http://JavaScript.FAQTs.com/
     
    Martin Honnen, Nov 20, 2005
    #8
  9. Raphael Jolivet wrote in news:ux%ff.1569$ 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.
    --
    http://www.victim-prime.dsl.pipex.com/
     
    Rob Williscroft, Nov 20, 2005
    #9

  10. > 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.
     
    Raphael Jolivet, Nov 20, 2005
    #10
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ook
    Replies:
    10
    Views:
    558
  2. Florian Frank
    Replies:
    0
    Views:
    244
    Florian Frank
    Jun 30, 2009
  3. thunk
    Replies:
    1
    Views:
    315
    thunk
    Mar 30, 2010
  4. thunk
    Replies:
    0
    Views:
    489
    thunk
    Apr 1, 2010
  5. thunk
    Replies:
    14
    Views:
    627
    thunk
    Apr 3, 2010
Loading...

Share This Page