Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 6 of 6
  1. #1
    New to the CF scene
    Join Date
    Oct 2009
    Posts
    6
    Thanks
    1
    Thanked 0 Times in 0 Posts

    Unhappy Shared Prototype Objects

    Hi everybody,

    I'm having a little problem with JavaScript and Object Prototypes. I have been working with simple uses of the Object but as I get into more complex scenarios, like inheritance, I seem to be missing something basic about the whole Constructor, Prototype, and Object relationship.

    My specific question is - How do you create an Object that points back to a Prototype Object created earlier for another Object using the same Constructor. For instance, sorry this is complex:

    If I have a simple hierarchy of Objects where OneObj is at the top and TwoObj is in the middle and ThreeObj is at the bottom. In this scenario OneObj is parent to TwoObj which in turn is parent to ThreeObj. Then I want to create a Prototype Chain like so:

    ThreeObj.prototype = new OneObj();
    ThreeObj.prototype.constructor = ThreeObj;
    var objA = new ThreeObj();

    At the start of the script I create an Object 'objA' using just two of our three objects. At this point all is good. Then I want to create a slightly different Object introducing a new Constructor (TwoObj) that I add to the Prototype Inheritance

    TwoObj.prototype = new OneObj();
    TwoObj.prototype.constructor = TwoObj;
    ThreeObj.prototype = new OneObj();
    ThreeObj.prototype.constructor = ThreeObj;
    var objB = new ThreeObj();

    When run objB is well formed and meets my expectations; however, when I try to go back and create a new object from the first scenario like this:

    ThreeObj.prototype = new OneObj();
    ThreeObj.prototype.constructor = ThreeObj;
    var objC = new ThreeObj();

    Here is where I have a problem. I would expect that objC and objA would share Prototypes (point to the same Prototype Object). But when I added a new property to objC like:

    objC.constructor.prototype.propNew = 18;

    It only shows up in objC's Prototype and not objA's. I thought this might be because I was setting the ThreeObj.prototype = new OneObj() and the new OneObj was an new instantiation so perhaps it cannot be shared! So the next test was to use the prototype from objA. I did this as follows:

    ThreeObj.prototype = objA.constructor.prototype;
    ThreeObj.prototype.constructor = ThreeObj;
    var objC = new ThreeObj();

    This time when I ran the test objA's Prototype still did not show the new property 'propNew' but this new property was shown in both objB's and objC's Prototype! What!!!!!

    So I beg you. Anyone who has a glimmer of an idea on why this happens this way please let me know while I still have some hair!

    TC

  • #2
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,371
    Thanks
    11
    Thanked 591 Times in 572 Posts
    you're making it too complicated:

    Code:
    function one(){
     this.one=1;
    }
    
    function two(){
     this.two=2;
    }
    
    function three(){
     this.three=3;
    }
    
    
    two.prototype=new one;
    three.prototype=new two;
    
    var ob=new three;
    
    ob.one + ob.two + ob.three == 6 ; //true
    
    ob instanceof three; // true
    ob instanceof two;   // true
    ob instanceof one;   // true
    Last edited by rnd me; 04-05-2013 at 12:52 AM.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/9/03) IE7:0.1, IE8:4.6, IE11:9.1, IE9:3.1, IE10:3.0, FF:17.2, CH:46, SF:11.4, NON-MOUSE:38%

  • #3
    New to the CF scene
    Join Date
    Oct 2009
    Posts
    6
    Thanks
    1
    Thanked 0 Times in 0 Posts
    Hi rnd me,

    You don't seem to have addressed my question. When I add a new property to objC's Constructor's Prototype it was not visible in objA, which I thought would share Prototypes.

    I understand why the Constructor properties in your example add to 6. Though I see you have left out the relinking of the Constructor. Is that the way it should be done?

    That is you did not -

    two.prototype=new one();
    two.prototype.constructor = two; // relinked
    three.prototype=new two();
    three.prototype.constructor = three; // relinked

    Crap I notice I have some typos in my earlier post sorry, this is the corrected Prototype Chain:

    TwoObj.prototype = new OneObj();
    TwoObj.prototype.constructor = TwoObj;
    ThreeObj.prototype = new TwoObj(); // Changed!
    ThreeObj.prototype.constructor = ThreeObj;
    var objB = new ThreeObj();

    Appreciate your input.

    TC

  • #4
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,371
    Thanks
    11
    Thanked 591 Times in 572 Posts
    ok, this is kinda complex so pardon the multi-quote, which typically is used to rudely take pot shots at other posters...


    Quote Originally Posted by throwcode View Post
    Hi rnd me,
    You don't seem to have addressed my question. When I add a new property to objC's Constructor's Prototype it was not visible in objA, which I thought would share Prototypes.
    objC has a different prototype than objA; both are distinct instances of OneObj in your orig post. you pulled a switcharoo on the proto between the instantiations. if an instance inherits something through it's constructor's prototype, and you re-assign the contructor's prototype and create a new instance, you're tacking on the new prototype to the newer object, not the old one.


    a side-effect test of this would be if ".prototype=new " appears between the two instantiations. Since your code is partial in your replay and typoed in your orig post, i'm not 100% sure what your current setup is, but if you re-assign a property, you re-assign a property, no matter where it ends up poking its head.


    Essentially, you're one level too high, one dot to the left, or however you want to think of it. you can modify an existing prototype for instant system-wide inheritance, but you cannot replace it completely and get the same satisfaction.


    Interestingly, you can .call() a constructor to a prototype so that all existing instances will get the own properties of that constructor's instance, but that's not 100% the same as what you're after..

    ex:
    Code:
    function Text(){
      this.quoted=function(){return '"'+this+'"'};
    }
    
    Text.call(String.prototype);
    
    new String(123).quoted() // === "\"123\""
    this is typically a lot faster (execution-wise) than iterating properties to merge objects or fake a more formalized deep inheritance.


    Quote Originally Posted by throwcode View Post
    I understand why the Constructor properties in your example add to 6. Though I see you have left out the relinking of the Constructor. Is that the way it should be done?
    once you have a 3rd nesting of a constructor, the "constructor" property is of little use. Actually, other than for sniffing native types (Array vs Object vs Date), it's pretty much useless anyway, and has a number of limitations and flaws. it would be great if it worked 100% in custom OOP getups, but it doesn't, so you should use other means to navigate.


    instanceof of will identify the instance with any sub-group of inherited properties (from the nested prototypes), whereas your "constructor" property just hits the most recent.

    another issue with setting the "constructor" property manually like that is that for(x in new ob) will dredge up that property, whereas in a native object instance like for(x in new String), "constructor" will not be an own property.

    compare:
    Code:
    function String2(){}
      String2.prototype=new String
      String2.prototype.constructor=String
      var s= new String2()
      var r=[]
      for(i in s){ r.push(i) }
    alert(r) //"constructor"
    versus:
    Code:
     var s= new String()
      var r=[]
      for(i in s){ r.push(i) }
    alert(r) //""
    functions don't show up in JSON.stringify, so the extra properties might not hurt your project, but be aware of them...



    anyway, our code is similar, i just didn't manually set the constructor property, which we don't need to do. since it can be re-assigned, and it's relative, it can be confusing to work with and explicitly comparing an object to any constructor in it's chain is fool-proof.


    feel free to post you current whole code if that doesn't make sense and we'll see if i or someone else can explain it better for your exact issue.
    Last edited by rnd me; 04-05-2013 at 05:32 AM.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/9/03) IE7:0.1, IE8:4.6, IE11:9.1, IE9:3.1, IE10:3.0, FF:17.2, CH:46, SF:11.4, NON-MOUSE:38%

  • Users who have thanked rnd me for this post:

    throwcode (04-05-2013)

  • #5
    New to the CF scene
    Join Date
    Oct 2009
    Posts
    6
    Thanks
    1
    Thanked 0 Times in 0 Posts
    Hi rnd me,

    First let me thank you for all the time you've taken so far. I admit that I am still noodling over your comments. I'm afraid there is no convenient source to review. When I ran into this problem this is the test code I created to walk through the various scenarios. It was meant to be simpler!

    But thanks to you and what I understand so far I have a partial solution.

    By removing the reset of the Prototype's 'constructor' property I can now see the new properties and methods being added to what I believe are the correct Prototype levels for the right Object Instantiations. Thanks for that.

    However, this has allowed me to look deeper and discover another result that I cannot explain. The following code gives me two different results:

    objC.constructor.prototype.propNew = 18;
    Object.getPrototypeOf(objC).propNew = 18;

    I would have expected these two statements to be the same; however, the first appears in ALL of the Objects (objA,objB,objC) whereas the second only appears in objC's Prototype Chain.

    When I test the value returned for each Prototype I receive [object Object] for the first and Object 'OneObj' for the second.

    Any thoughts on why these do not return the same Prototype Object? Or why they behave differently?

    Much Thanks
    TC

  • #6
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,371
    Thanks
    11
    Thanked 591 Times in 572 Posts
    Quote Originally Posted by throwcode View Post
    objC.constructor.prototype.propNew = 18;
    Object.getPrototypeOf(objC).propNew = 18;

    Any thoughts on why these do not return the same Prototype Object? Or why they behave differently?
    i'm not sure from just what's in front of me, please post your whole code top to bottom and i'll be happy to take a look.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/9/03) IE7:0.1, IE8:4.6, IE11:9.1, IE9:3.1, IE10:3.0, FF:17.2, CH:46, SF:11.4, NON-MOUSE:38%


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •