www.webdeveloper.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 19

Thread: Passing by reference ??

  1. #1
    Join Date
    Apr 2005
    Posts
    92

    Passing by reference ??

    Hi all

    According to all manuals that I've read javascript objects (and functions are objects in JS) are passed by reference when assigned to variables. I have a problem where this doesn't seem to be the case.

    First I write my constructor:

    Code:
    function NewObj() {
    }
    Second I declare a prototype function

    Code:
    NewObj.prototype.onclick = function() {alert('Initial onclick function')};
    Now I write a third function which will create a DIV object and assign the onclick event handler associated with my object.

    Code:
    function createHTML() {
      var thisObj = new NewObj();
      var elm = document.createElement("DIV");
      elm.onclick = thisObj.onclick;
      document.body.appendChild(elm);
    }
    Now the DIV element is attached to the document and when I click it it will alert ' Initial onclick function';

    However if I now change my prototype function to

    Code:
    NewObj.prototype.onclick = function() {alert('New onclick function');};
    this change is not reflected in my DIV element and when clicked it will still execute the first event handler function. This leeds me to believe that the line

    Code:
    elm.onclick = thisObj.onclick;
    is copied by value and NOT by reference. I tried using different scopes for my variable declarations and used every possible way of declaring the prototype functions but still it won't work.

    Does anyone have a clue why this is?

  2. #2
    Join Date
    Dec 2002
    Location
    Calgary, Canada
    Posts
    6,120
    how did you make changes to the prototype at run time, I bet logic has to do with it.
    JavaScript does pass by ref
    Cheers

    Khalid

    Message Posting Guidelines In These Forums, Please read these before posting any question.
    Web site: webapplikations.com
    Web Resources Page:Web Resources

  3. #3
    Join Date
    Oct 2004
    Posts
    1,118
    This leeds me to believe that the line

    elm.onclick = thisObj.onclick;

    is copied by value and NOT by reference.
    Nothing is actually "passed by reference"--everything is passed by value. The only question is whether you are passing an address by value or the whole object by value, i.e. whether only an address is being copied or the whole object is being copied.

    A reference is actually the "address" in memory where an object is located. An address looks something like this:

    456AF213

    Don't be frightened by that. It's just a number, actually a simple integer, and it indicates where the object resides in memory. Now, as to why that is relevant. This is what you start out doing:

    var RefA = obj;
    var RefB = RefA;

    The issue you are wrestling with is: does RefB refer to RefA or directly to obj? You started out believing RefB refers to RefA, and therefore any change to RefA would be reflected in RefB. However, that is incorrect. RefB refers directly to obj, and by examining what is happening with the "address", you can see why. If obj is at some location in memory signified by:

    456AF213

    then when you assign obj to RefA:

    var RefA = obj;

    the address is assigned to the variable RefA, and you end up with this:

    RefA = 456AF213

    Substituting for RefA in the second assignment:

    var RefB = RefA;

    gives you:

    var RefB = 456AF213;

    The assignment just copies the address stored in RefA to RefB. Subsequently, if you change obj in some way, then both RefA and RefB will reflect that change--revealing that they are in fact references. For instance:

    obj.new_property = "red";
    alert(RefA.new_property); //"red"
    alert(RefB.new_property); //"red"

    However, if you change RefA to refer to some other object, it has no effect on RefB. For instance:

    RefA = another_obj;

    Since another_obj will be at a unique place in memory, objRef will get assigned a new "address":

    RefA = 1234AE24

    However, that assignment in no way affects RefB, and RefB will still refer to obj.

    That may be explanation enough for you. However, if you still have some lingering suspicions, read on. The crux of your dilemma is that there is a fundamental difference in the two assignments:

    var RefA = obj;
    var RefB = RefA;

    This is the situation in memory just before the second assignment:
    Code:
       obj            RefA=456AF213                 RefB
    ---------          ----------                ----------
    456AF213            1344AC45                  9245AD23
    In the first assignment:

    var RefA = obj;

    the assignment works this way: js takes the address of what's on the right and assigns it to the variable on the left:

    var RefA <---- address of obj

    In the second assignment:

    var RefB = RefA;

    if the assignment worked the same way, then the address of what's on the right, i.e. RefA, would be assigned to RefB. RefA is a separate variable in its own right, and therefore it has its own address, as shown in the diagram. If the second assignment worked the same way, the result would be:

    Code:
       obj            RefA=456AF213             RefB=1344AC45
    ---------          ----------                ----------
    456AF213            1344AC45                  9245AD23
    and then any changes to RefA would also affect RefB because RefB would be a reference to RefA. However, before the assignment takes place, js examines what is on the right side of the equals sign. If to the right of the equals sign there is an object, e.g. a function, then js takes the address of that object and assigns it to the variable on the left of the equals sign. However, if js finds a reference on the right side of the equals sign, then js just copies the address stored in the reference and assigns it to the variable on the left.

    or ?
    Last edited by 7stud; 04-15-2005 at 12:13 AM.

  4. #4
    Join Date
    Apr 2005
    Posts
    92
    7stud>
    I know all this but thanks anyway...the problem is that a property change in my object (thisObj) is not reflected in the DIV element (elm) I create. The properties of the DIV element are supposed to be references to the properties of the object.

    Khalid>
    I suspect as well that it might have to do with changing prototype functions at run time. Here's the complete source (init() is called by the onload event):

    Code:
    // Constructor
    function NewObj() {
    }
    // Onclick before change
    NewObj.prototype.onclick =
      function() {
        alert("Initial onclick function");
      };
    // Wrap obcject in HTML
    NewObj.prototype.toHTML =
      function() {
        var elm = document.createElement("DIV");
        // Set style
        elm.className = "test";
        elm.onclick = this.onclick;
        document.body.appendChild(elm);
      };
    // Executed on onload
    function init() {
      var thisObj = new NewObj
      thisObj.toHTML();
      // Change onclick function
      NewObj.prototype.onclick =
        function() {
          alert("new onclick function");
        };
    }
    I tried declaring both thisObj and elm in the global scope. Also tried to use the 'new Function' constructor for the onclick functions. When the DIV element is clicked it still alerts 'initial onclick function'.

  5. #5
    Join Date
    Oct 2004
    Posts
    1,118
    I know all this but thanks anyway
    Your welcome, but it's abundantly clear to me that you don't--otherwise you would understand why your code doesn't work.
    The properties of the DIV element are supposed to be references to the properties of the object.
    No. The poperties of the DIV are references, but to what is the question. In js, you can't have two levels of indirection, i.e. you can't get one variable that refers to another variable that refers to an object. All you can get is two variables that refer to the object. If you can't understand why from reading my post, then you just have to take that on faith (actually the why of it boils down to that's the way the creators of js defined the assignment operator, which means the reason ultimately is: "that's the way it is" ). You can get this:
    Code:
    Ref1  ------->
                  object
    Ref2  ------->
    but you can't get this:
    Code:
    Ref1---->Ref2---->object
    That's my understanding. Sorry if it didn't help.
    Last edited by 7stud; 04-15-2005 at 06:43 AM.

  6. #6
    Join Date
    Oct 2004
    Posts
    1,118
    ....
    Last edited by 7stud; 04-15-2005 at 06:02 AM. Reason: duplicate

  7. #7
    Join Date
    Apr 2005
    Posts
    92
    my question as well...

  8. #8
    Join Date
    Apr 2005
    Posts
    92
    7Stud>
    Ahh...I see what you mean now - sorry I misunderstood your first post. Still I don't really see how the 'refA -> refB -> obj' applies here.

    I create an object obj. This object holds the prototype function onclick. Then I create a DIV element elm. Setting elm.onclick = obj.onclick is as I see it 'refA -> obj'.

    Am I wrong again?

  9. #9
    Join Date
    Oct 2004
    Posts
    1,118
    Here is what you are doing:
    Code:
    NewObj.prototype.onclick =  function() {alert("Initial onclick function");
    ...
    ...
    var thisObj = new NewObj;
    thisObj.toHTML()--->elm.onclick = this.onclick;
    'this' is a reference to thisObj, so substituting for 'this', you have:

    elm.onclick = thisObj.onclick

    After searching the thisObj object for an onclick property, js can't find the property, so js searches the NewObj.prototype object for the property, and js finds onclick there. So, your statement becomes:

    elm.onclick = NewObj.prototype.onclick;

    Since NewObj.prototype.onclick is a reference to your function, you have this relationship:

    elm.onclick = NewObj.prototype.onclick = function() {alert("Initial onclick function");

    That is the same as: refA ---> refB ---> obj

    Here are the rules again:
    ...before the assignment takes place, js examines what is on the right side of the equals sign. If to the right of the equals sign there is an object, e.g. a function, then js takes the address of that object and assigns it to the variable on the left of the equals sign. However, if js finds a reference on the right side of the equals sign, then js just copies the address stored in the reference and assigns it to the variable on the left.
    You can apply those rules to what is happening in your code:

    1)
    Code:
    NewObj.prototype.onclick =  function() {alert("Initial onclick function");
    js sees an object on the right of the equals sign, so it fetches the object's address and assigns it to the prototype's onclick property. If the object resides at address 10A, this is what happens:

    NewObj.prototype.onclick = 10A;

    2)
    Code:
    var thisObj = new NewObj
    Once again, js sees an object on the right of the equals sign, so it fetches the object's address and assigns it to thisObj. If newObj resides at address 2B, then this is what happens:

    this.Obj = 2B;

    3)
    Code:
    thisObj.toHTML()--->elm.onclick = this.onclick;
    'this' is a reference to thisObj, so substituting for 'this', you have:

    elm.onclick = thisObj.onclick

    After searching thisObj for onclick, js can't find the property, so js searches the NewObj.prototype object for the property, and finds onclick there. The statement becomes:

    elm.onclick = NewObj.prototype.onclick;

    With that assignment, js doesn't find an object on the right side of the equals sign because in step 1) NewObj.prototype.onclick was assigned an address. When js sees a variable on the right side of the equals sign with an address stored in it, js does not fetch the address where the variable resides in memory. Instead, js copies the address stored in the variable on the right, and copies it to the variable on the left. That results in:

    elm.onclick = 10A;

    So, all together you have:

    Code:
    function() {alert("Initial onclick function");
    ----------------------------------------
                   10A
    
    NewObj.prototype.onclick = 10A;
    elm.onclick = 10A
    If you subsequently do this:

    NewObj.prototype.onclick = function() {alert("NEW onclick function");

    and the new function is stored in memory at address 30C, you are left with:

    Code:
    function() {alert("Initial onclick function");
    ------------------------------------
                       10A
    
    
    function() {alert("NEW onclick function");
    ---------------------------------
                      30C
    
    elm.onclick = 10A
    NewObj.prototype.onclick = 30C;
    elm.onclick is unchanged, and elm.onclick and NewObj.prototype.onclick refer to different functions.
    Last edited by 7stud; 04-16-2005 at 01:07 AM.

  10. #10
    Join Date
    Apr 2005
    Posts
    92
    I forgot to think of the 'NewObj.prototype.onclick = function...' as a reference. Execellent description. Thanks a lot.

    I am working on a project where I have all my data stored in JS objects. When ever the data is displayed I need to wrap it in some kind of HTML. Is there in your opinion a more clever way to do this than the approach I am using?

  11. #11
    Join Date
    Oct 2004
    Posts
    1,118
    Hi,

    I think you have to abandon prototype inheritance, but there is another way to create class wide properties. A function is an object, so even though it may seem strange, you can attach properties to it:
    Code:
    function NewObj(){}
    NewObj.color = "red";
    alert(NewObj.color); //red
    Or, this:
    Code:
    function NewObj(){}
    NewObj.onclick = function(){alert("Initial onclick function")};
    NewObj.onclick();
    So, you can take advantage of that ability, like this:
    Code:
    function NewObj()
    {
    	this.onclick = function(){NewObj.onclick()}; 
    	//reference to a function that executes NewObj.onclick
    }
    
    //assign a function to NewObj.onclick:
    NewObj.onclick=function(){alert("Initial onclick function")};
    
    thisObj = new NewObj();
    thisObj.onclick(); //displays: "Initial onclick function"
    
    //change the function assigned to NewObj.onclick:
    NewObj.onclick = function(){alert("New onclick function")};
    
    thisObj.onclick();  //displays: "New onclick function"
    Last edited by 7stud; 04-16-2005 at 06:13 PM.

  12. #12
    Join Date
    Oct 2004
    Posts
    1,118
    Hi,

    I was thinking about your code some more, and there is another solution. The previous solution involves assigning a property to the constructor function, but the constructor function is just like any other object, so it's just like a prototype object. So, you should be able to do something similar to the prototype object.

    In the previous solution I posted, the trick to solving your problem was this line:

    this.onclick = function(){NewObj.onclick()};

    You should be able to do something similar with your original code and the prototype object. In your origninal code, you did this:

    elm.onclick = this.onclick;

    So, as a first attempt you might try to apply the same principle as above and wrap a function around this.onclick:

    elm.onclick = function(){this.onclick()};

    I suggest you try that and see what happens. Then, see if you can solve the problem it creates.
    Last edited by 7stud; 04-17-2005 at 12:05 AM.

  13. #13
    Join Date
    Dec 2002
    Location
    Calgary, Canada
    Posts
    6,120
    Quote Originally Posted by 7stud
    Nothing is actually "passed by reference"--everything is passed by value.
    now this statement is surprising, I wonder if you do understand the subtle difference between "passed by value" and "passed by reference" approaches.
    Cheers

    Khalid

    Message Posting Guidelines In These Forums, Please read these before posting any question.
    Web site: webapplikations.com
    Web Resources Page:Web Resources

  14. #14
    Join Date
    Oct 2004
    Posts
    1,118
    I wonder if you do understand the subtle difference between "passed by value" and "passed by reference" approaches.
    Well, I understand something, and you're welcome to probe the extent of that understanding. But, before we start such a discussion, what are your definitions of "passing by value" and "passing by reference", and how do they differ?
    Last edited by 7stud; 04-17-2005 at 01:56 AM.

  15. #15
    Join Date
    Dec 2002
    Location
    Calgary, Canada
    Posts
    6,120
    for you and any one else out there who actually want to know the difference, here it is.

    Passing by value
    if a parameter is passed by value, this means that the function will create a copy of the original object(prameter) and make changes to that copy locally which means original object that was created at whatever stage in the program will hold its initial value.

    Passing by reference
    in this type of parameter passing the actuall memory address of an object(parameter) is passed, hence any changes made to that variable/object in any give function will reflect the changes on the original object that was created at whatever stage in the program.

    Now as far as JavaScript is concern, when you declare a global variable, and you pass it as parameter, this variable will be passed by value and is local for that function where it was passed on as param, Hope this clears it. I'd rather not discuss this issue any more, if you still have questions then buy a good programming book on how all this works and then come back and try to give advice on such issue.
    Cheers

    Khalid

    Message Posting Guidelines In These Forums, Please read these before posting any question.
    Web site: webapplikations.com
    Web Resources Page:Web Resources

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

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



Recent Articles