Results 1 to 4 of 4

Thread: Array assignment causes unexpected modification to a separate array

  1. #1
    Join Date
    Feb 2012
    Posts
    2
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default Array assignment causes unexpected modification to a separate array

    Hi,

    I am seeing an unexpected behaviour in the following code which I cannot explain however both FF and IE give the same result so the problem must be in my code.

    I have reduced it to the following where I have 2 internal arrays a and b that are initialised to the same value T (which is an array).

    If I make an update to one array I see the result in both a and b.

    This only happens if I pass an array type. If I pass a single string (and re-code to remove [0] references) then the assignment to b does not update a.


    What is the issue with using array's like this and why does the assignment to b cause a to take the same value?


    The alerts display:

    a Before : A,B
    b Before : A,B

    a After : X,B <<<<< WHY???
    b After : X,B


    Code:
        <script language="JavaScript">
    
          function test(T) {
    
            this.a = T;
            this.b = T;
       
              // As expected both a and b display "A,B"
              alert("a Before : "+this.a+"\nb Before : "+this.b);
    
              // only update b
              this.b[0]="X"; 
    
              // why does a show the updated value of b?
              alert("a After : "+this.a+"\nb After : "+this.b); 
          } 
    
          var tmp=new Array("A","B");
          theTest=new test(tmp);
    
        </script>

  2. #2
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    28,926
    Thanks
    43
    Thanked 3,190 Times in 3,154 Posts
    Blog Entries
    12

    Default

    There's only one array. If you were to alert(tmp), it also would be X,B.

    Unlike a literal string value which is copied when another variable or reference is set equal to it, an array is an object. Unless you make a new array that is a copy of it, it's the same array regardless of how many variables or other references you assign it to.

    There are I suppose various ways to copy an array. Two that spring to mind are:

    Code:
    <script type="text/javascript">
          function test(T) {
    
            this.a = [];
            this.b = [];
            
            for (var i = T.length - 1; i > -1; --i){
            	this.a[i] = this.b[i] = T[i];
            }
       
              // As expected both a and b display "A,B"
              alert("a Before : "+this.a+"\nb Before : "+this.b);
    
              // only update b
              this.b[0]="X"; 
    
              // the arrays a, b and T(tmp) are separate now. a and T(tmp) are still A,B, b is X,B
              alert("a After : "+this.a+"\nb After : "+this.b); 
          } 
    
          var tmp=new Array("A","B");
          theTest=new test(tmp);
    </script>
    And:

    Code:
    <script type="text/javascript">
          function test(T) {
    
            this.a = [].concat(T);
            this.b = [].concat(T);
            
              // As expected both a and b display "A,B"
              alert("a Before : "+this.a+"\nb Before : "+this.b);
    
              // only update b
              this.b[0]="X"; 
    
              // the arrays a, b and T(tmp) are separate now. a and T(tmp) are still A,B, b is X,B
              alert("a After : "+this.a+"\nb After : "+this.b); 
          } 
    
          var tmp=new Array("A","B");
          theTest=new test(tmp);
    </script>
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  3. #3
    Join Date
    Feb 2012
    Posts
    2
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default

    Hi John,

    Thanks for your help and the clear explanation - I had assumed that creating a new object of test would in turn create internal array elements within that object.

    Glad I now know that's not the case!


    Can I ask if there is a special reason why you used a decrementing loop starting at T.length and testing for i>-1? Is there added benefit to that approach compared to starting an incrementing loop at 0 and testing for <T.length?

    Regards,
    Vince.

  4. #4
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    28,926
    Thanks
    43
    Thanked 3,190 Times in 3,154 Posts
    Blog Entries
    12

    Default

    Not only is it a decremental loop, it's also pre-decrements (--i) as opposed to post-decrement (i--). Whether incrementing or decrementing, time trilas have shown the pre method is faster, as is the decremental loop over the incremental. In this application (because it's such a small array) there really isn't any material advantage to the decremental loop or pre-decrementing i.

    In some cases, it's actually less serviceable than an incremental loop, like where you're looking for the first match or match like expression of something where there could be more than one and then breaking from the loop.

    However, in cases where items are being removed from the array or from the DOM during the loop, it's virtually required. Otherwise the loop will lose count as the array or array like node list or element collection changes size.

    As a result I usually use the decremental loop with pre-decrementing, only using the incremental one when required, and then only with pre-incrementing. I regard this as just good general practice regardless of the fact that most people first learn and still almost always use the incremental with post-incrementing.
    Last edited by jscheuer1; 03-01-2012 at 03:48 PM.
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

Bookmarks

Posting Permissions

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