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 12 of 12
  1. #1
    Regular Coder
    Join Date
    Oct 2009
    Posts
    189
    Thanks
    38
    Thanked 3 Times in 3 Posts

    Passing object by reference question

    My question is commented in the script:

    Code:
    function Love(){
    	var req = {
    		ring : 'gold',
    		money : 'a lot',
    		commitment : 'long-term'
    	}
    	
    	this.loveReqs = function(){
    		return req;
    	}
    }
    
    var you = new Love();
    var details = you.loveReqs();
    details.ring = "silver";
    console.log(details.ring);
    
    
    var me = new Love();
    var details = me.loveReqs();
    console.log(details.ring); // why does this return gold and not silver if req is passed by reference and we already changed its value above and so it's pointing to the same memory position?

  • #2
    Regular Coder
    Join Date
    Aug 2010
    Posts
    970
    Thanks
    19
    Thanked 212 Times in 210 Posts
    Quote Originally Posted by johnmerlino View Post
    My question is commented in the script:

    Code:
    function Love(){
    	var req = {
    		ring : 'gold',
    		money : 'a lot',
    		commitment : 'long-term'
    	}
    	
    	this.loveReqs = function(){
    		return req;
    	}
    }
    
    var you = new Love();
    var details = you.loveReqs();
    details.ring = "silver";
    console.log(details.ring);
    
    
    var me = new Love();
    var details = me.loveReqs();
    console.log(details.ring); // why does this return gold and not silver if req is passed by reference and we already changed its value above and so it's pointing to the same memory position?
    The value of req is not change in this code.The value returned by
    me.loveReqs() stored in details has been altered.

  • #3
    Senior Coder Logic Ali's Avatar
    Join Date
    Sep 2010
    Location
    London
    Posts
    1,028
    Thanks
    0
    Thanked 207 Times in 202 Posts
    Quote Originally Posted by johnmerlino View Post
    var you = new Love();
    var details = you.loveReqs();
    details.ring = "silver";
    console.log(details.ring);


    var me = new Love();
    var details = me.loveReqs();
    console.log(details.ring); // why does this return gold and not silver if req is passed by reference and we already changed its value above and so it's pointing to the same memory position?
    [/CODE]
    you and me are different instances, so why would a change to a property of one be reflected in the other?

  • #4
    Regular Coder
    Join Date
    Oct 2009
    Posts
    189
    Thanks
    38
    Thanked 3 Times in 3 Posts
    But req is a private variable and therefore not part of the returned object when constructor is called:

    Code:
     
    function Love(){
            // var this = Object.create(Love.prototype);
    
    	var req = {
    		ring : 'gold',
    		money : 'a lot',
    		commitment : 'long-term'
    	}
    	
    	this.loveReqs = function(){
    		return req;
    	}
    
         //return this;
    }
    So req is an own member of Love and never part of the you instance. req is only accessible because of the closure created. However, it's still not part of the instance. But we can access it through the "privileged" method.

    Nevertheless, we call the privileged method and assign its returned object (req) to variable a:

    Code:
    var you = new Love();
    var a = you.loveReqs();
    a.ring = "silver";
    console.log(a.ring);
    So when we return the object and assign it to variable a, a now points to the original object, which is a private property not accessible to the instance, no? If it points to original object, then this does too:

    Code:
    var me = new Love();
    var b = me.loveReqs();
    console.log(b.ring);
    Hence, since b is pointing to what a is pointing to, the value should be the same. Isn't that what passing by reference is all about?

    Thanks for response.
    Last edited by johnmerlino; 01-03-2011 at 09:31 PM.

  • #5
    Regular Coder
    Join Date
    Aug 2010
    Posts
    970
    Thanks
    19
    Thanked 212 Times in 210 Posts
    Code:
    <html>
    <head>
      <title> pointers? </title>
    </head>
    <body>
      <div id="container">&nbsp;</div>
    <script type="text/javascript">
     function Love(){
    	req = {
    		ring : 'gold',
    		money : 'a lot',
    		commitment : 'long-term'
    	}	
    	this.loveReqs = function(){
    		return req;
    	}
    }
    var details;
    var you = new Love();
    details = you.loveReqs();
    document.write('here ring = ' + details.ring + ' as expected <br>');
    req.ring = 'x';
    document.write('here we have changed ring to ' + details.ring + ' by changing the req object <br>');
    document.write('But as you can see from the alerted code a new instance of Love will set req.ring to gold <br>');
    alert(Love)
    var me = new Love();
    details = me.loveReqs();
    document.write('here ring again equals ' + details.ring ); 
    </script>
    </body>
    </html>

  • #6
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,447
    Thanks
    76
    Thanked 4,372 Times in 4,337 Posts
    req is only accessible because of the closure created. However, it's still not part of the instance.
    Actually, it is part of the instance. It's not *accessible* directly through an instance of Love, but nevertheless the fact that you used a closure means that indeed each instance of Love will have its own copy.

    If you think about it, there's no other way that closures can work. The whole point of a closure is to create a value that is private to each instance of a function. If that didn't happen, closures would be worthless. The fact that in this case the function is being used as a constructor doesn't change how the closure should and does work.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #7
    Regular Coder
    Join Date
    Oct 2009
    Posts
    189
    Thanks
    38
    Thanked 3 Times in 3 Posts
    But aren't prototype properties not recreated when new instance is called with constructor?

    Take a look:
    Code:
    function Love(){
    	var z = {a : 'a'};
     	this.getZ = function(){
    		return z;
    	}
    }
    
    var inst = new Love();
    var ref = inst.getZ();
    ref.a = 'abc'; 
    console.log(inst.getZ()); //output:  Object { a="abc"} - Again this proves that object is passed by reference because when we called getZ() the first time, we assigned the returned object to another object, and when changing the values on the other object, it changed the values on the inst object.
    
    var inst2 = new Love();
    console.log(inst2.getZ()); //output:  Object { a="a"} - This proves when we instantiate and call constructor, it recreates its own members and so inst2 is now dealing with a totally different object.
    
    //However, we are told that prototype does not recreate the members and so the prototype properties are shared across all instances:
    Love.prototype = {
    	getB : function(){
    		return {key : 'value'};
     	} 
    }
    
    var instance = new Love();
    var instance_variable = instance.getB();
    instance_variable.key = "property's value";
    var instance2 = new Love();
    var instance_variable2 = instance2.getB();
    console.log(instance_variable2.key); // output is "value" not "property's value"!
    Why does it refer to the original property again if we changed it in the instance_variable instance and if all instances share same prototype, meaning that prototype properties are NOT recreated whenever constructor is called, then that property should have been permanently changed. But obviously it's not.

    Thanks for response.

  • #8
    Regular Coder
    Join Date
    Aug 2010
    Posts
    970
    Thanks
    19
    Thanked 212 Times in 210 Posts
    Code:
    <html>
    <head>
      <title> which object ? </title>
    </head>
    <body>
      <div id="container">&nbsp;</div>
    <script type="text/javascript">
     function Love(){
    	var z = {a : 'a'};
     	this.getZ = function(){
    		return z;
    	}
    }
    
    var inst = new Love();
    var ref = inst.getZ();
    ref.a = 'abc'; 
    document.write(inst.getZ()); //output:  Object { a="abc"} - Again this proves that object is passed by reference because when we called getZ() the first time, we assigned the returned object to another object, and when changing the values on the other object, it changed the values on the inst object.
    
    var inst2 = new Love();
    document.write(inst2.getZ()); //output:  Object { a="a"} - This proves when we instantiate and call constructor, it recreates its own members and so inst2 is now dealing with a totally different object.
    
    //However, we are told that prototype does not recreate the members and so the prototype properties are shared across all instances:
    Love.prototype = {
    	getB : function(){
    		return {key : 'value'};
     	} 
    }
    
    var instance = new Love();
    var instance_variable = instance.getB();
    instance_variable.key = "property's value";
    alert(Love.prototype.getB)
    Love.prototype = {
    	getB : function(){
    		return {key : "property's value"};
     	} 
    }
    var instance2 = new Love();
    var instance_variable2 = instance2.getB();
    document.write(instance_variable2.key); // output is "property's value"!
    
    </script>
    </body>
    </html>
    johnmerlino said ...
    "Why does it refer to the original property again if we changed it in the instance_variable instance and if all instances share same prototype, meaning that prototype properties are NOT recreated whenever constructor is called, then that property should have been permanently changed. But obviously it's not. "

    Because the value of Love.prototype.getB is not changed

  • Users who have thanked DaveyErwin for this post:

    johnmerlino (01-05-2011)

  • #9
    Regular Coder
    Join Date
    Oct 2009
    Posts
    189
    Thanks
    38
    Thanked 3 Times in 3 Posts
    Quote Originally Posted by DaveyErwin View Post
    Code:
    <html>
    <head>
      <title> which object ? </title>
    </head>
    <body>
      <div id="container">&nbsp;</div>
    <script type="text/javascript">
     function Love(){
    	var z = {a : 'a'};
     	this.getZ = function(){
    		return z;
    	}
    }
    
    var inst = new Love();
    var ref = inst.getZ();
    ref.a = 'abc'; 
    document.write(inst.getZ()); //output:  Object { a="abc"} - Again this proves that object is passed by reference because when we called getZ() the first time, we assigned the returned object to another object, and when changing the values on the other object, it changed the values on the inst object.
    
    var inst2 = new Love();
    document.write(inst2.getZ()); //output:  Object { a="a"} - This proves when we instantiate and call constructor, it recreates its own members and so inst2 is now dealing with a totally different object.
    
    //However, we are told that prototype does not recreate the members and so the prototype properties are shared across all instances:
    Love.prototype = {
    	getB : function(){
    		return {key : 'value'};
     	} 
    }
    
    var instance = new Love();
    var instance_variable = instance.getB();
    instance_variable.key = "property's value";
    alert(Love.prototype.getB)
    Love.prototype = {
    	getB : function(){
    		return {key : "property's value"};
     	} 
    }
    var instance2 = new Love();
    var instance_variable2 = instance2.getB();
    document.write(instance_variable2.key); // output is "property's value"!
    
    </script>
    </body>
    </html>
    johnmerlino said ...
    "Why does it refer to the original property again if we changed it in the instance_variable instance and if all instances share same prototype, meaning that prototype properties are NOT recreated whenever constructor is called, then that property should have been permanently changed. But obviously it's not. "

    Because the value of Love.prototype.getB is not changed
    So what is changed is this.getB, where "this" refers to the current instance. So when you do:

    Code:
    var instance_variable = instance.getB();
    we are calling getB() part of the returned "this" object from the constructor. Hence, that getB() method was added as a property to the current object. So when we change its value:

    Code:
    instance_variable.key = "property's value";
    it will only affect the current instance and that which we passed by reference from the current instance.

    But the original method, which is the prototype of the Love constructor remains unchanged, as you show:

    Code:
    Love.prototype.getB
    Ultimately, you are changing the property of "this" not the actual prototype property of the Love constructor.

    If that's the case, then that makes sense. thanks.
    Last edited by johnmerlino; 01-06-2011 at 12:04 AM.

  • #10
    Regular Coder
    Join Date
    Oct 2009
    Posts
    189
    Thanks
    38
    Thanked 3 Times in 3 Posts
    Actually what I wrote above is wrong. THe properties of prototype are never attached as properties to the returned "this" object from the constructor. They always remain part of the Love object. When "this" is returned by the constructor during instantiation, somehow the JavaScript engine makes the properties of Love.prototype available to the instance, but they are not properties of "this" for the following reason:

    Code:
    var instance_variable = instance.getB();
    instance_variable.key = "property's value";
    console.log(Love.prototype.getB()); // output is "value"  
    console.log(instance.getB()); //output is "value"!!!!

    Yet you get different behavior with this:

    Code:
    var instant = new Love();
    var instant_obj = instant.getZ();
    instant_obj.a = 'd';
    console.log(instant.getZ()); // output is 'd' not 'a'
    So wen we modified the returned object when the method was declared in the constructor with this, this is altered. However, when we modify the returned object, and then return instance method, it is not changed by changes in returned object. Only conclusion is that the prototype properties are never attached to the returned instance. Yet somehow the returned instance can access them.

  • #11
    Regular Coder
    Join Date
    Oct 2009
    Posts
    189
    Thanks
    38
    Thanked 3 Times in 3 Posts
    Ok I think this is how it works. when you create the instance, it returns an object (return this). this has all the instance methods you created with this keyword packaged with the returned this object. Now when you call one of those methods of prototype, it's not part of "this". So the interpeter must resolve it. It goes one level up scope chain to the constructor of this. Interpreter notices that the method is not declared as an own member, so it checks the prototype and indeed it finds it. So it returns the method. But that method is never part of the returned object, explaining why we cannot alter it with the instance. Yet we are able to alter the instance methods packaged with "this".

  • #12
    Regular Coder
    Join Date
    Oct 2009
    Posts
    189
    Thanks
    38
    Thanked 3 Times in 3 Posts
    Alright ignore my posts above. After doing some research on ECMA, I'm pretty confident this is how it all works. I explain it in the comments:

    Code:
    function Love(){
    	//var this = Object.create(Love.prototype);	
     	this.getObj = function(){
    		return {a : 'a'};
    	}
    	
    	var z = {a : 'a'};
     	this.getZ = function(){
    		return z;
    	}
     	//return this;  
    }
    
    Love.prototype = {
    	getKey : function(){
    		return {key : 'value'};
     	}
    }
    
    var instant = new Love();
    var instant_obj = instant.getObj();
    console.log(instant_obj);
    var instant_obj2 = instant_obj;
    instant_obj.a = 'd';
    console.log(instant.getObj()); //Object {a="a"} - This returns original object and its key/value pairs because the object literal in the inner function may have access to the variables of outer function after function exits, courtesy of closure, but the variables in the inner function are themselves destroyed when function exits, meaning that when we call the function again, it returns a new object every single time. Now if we store the returned object in a variable, and then reference it in another object, then that object will be passed by reference and modifying one will modify the other. Check end notes
    console.log(instant_obj2.a); //'d' - objects passed by reference change
    
    var inst = new Love();
    var ref = inst.getZ();
    console.log(ref);
    ref.a = 'abc'; 
    console.log(inst.getZ()); //Object {a="abc"} - The reason why this returns "abc" is because the variable z is a closure (outside of the immediate function), so when we call the function again, changes to it are remembered. It has nothing to do with passing an object by referenece. 
    
     
    var instance2 = new Love();
    var instance_variable = instance2.getKey();
    var instance_variable2 = instance_variable;
    instance_variable.key = "property's value";
    console.log(instance2.getKey()); //Object {key="value"} - This returns original object and its key/value pairs because the object literal in the inner function may have access to the variables of outer function after function exits, courtesy of closure, but the variables in the inner function are themselves destroyed when function exits, meaning that when we call the function again, it returns a new object every single time. Now if we store the returned object in a variable, and then reference it in another object, then that object will be passed by reference and modifying one will modify the other. 
    //So the question remains how does the instance have access to getKey() if getKey() is part of the prototype of Love. The answer: The "new" operator will invoke your constructor passing in the specified parameters. A special variable named "this" will exist within the scope of the constructor (var this). "this" points to the current object instance (given that "this" is returned at the end of the constructor expression: return this;). Using "this" you can add and modify properties on the instance being created by the constructor (e.g. this.a = 'a'; this.fun = function(){}). all JS objects have a private prototype property. I say "private" because this property is not directly visible or accessible from the object itself (e.g. you don't say instance.prototype.getB()). When the runtime performs a lookup on a property, it first looks at the instance to see if that property is defined there. If it is not defined there, the runtime looks for the property on the object's private prototype. So how does the instance have access to getB() if it was initialized in the constructor's prototype? When new operator is invoked, it not only creates the new object, but it also assigns the constructor's prototype property (the publicly accessible one) to the new instance's private prototype. By defining properties on the constructor's prototype, like Love.prototype.getB(), we are creating properties that will be in the private prototype chain of each new instance. These become, in effect, instance methods. 
    
    console.log(instance_variable2.key); //property's value - objects passed by reference change


  •  

    Tags for this Thread

    Posting Permissions

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