SitePoint Sponsor

User Tag List

Results 1 to 7 of 7
  1. #1
    ********* Ornithologist AtomicPenguin's Avatar
    Join Date
    May 2002
    Location
    Vancouver, BC
    Posts
    459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Confused by scoping rules, perhaps...?

    This is interesting. Check out the following code - all I'm trying to do is populate a multi-dimensional array with a for-loop.

    Code:
     
     
    myArray = new Array();
     
    for (i=0; i<3; i++) {
      currentRowData = new Array();
      currentRowData.push(i + "_1");
      currentRowData.push(i + "_2");
      
      // store the data in global
      myArray.push(currentRowData);  
      
      // reset currentRowData for next loop
      currentRowData.length = 0; 
    }
     
    // why does this alert 'undefined', not '0_1' ? 
    alert(myArray[0][0]);
    Why does the alert() result in 'undefined'? By the looks of it, there's some scoping rule idiosyncrasy which I'm not familiar with. Anyone know a workaround?

  2. #2
    SitePoint Addict
    Join Date
    Mar 2003
    Location
    CA
    Posts
    210
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    each time you declare currentRowData you are declaring a new Array object, regardless of what you named it inside the loop. When you push the array onto myArray it is essentially pushing a reference onto myArray. When you se the currentRowData.length = 0 you are now accessing the reference in myArray and manipulating that object. Basically myArray.push(currentRowData) doesn't create a new copy of currentRowData, but rather push a reference (which gets automatically dereferenced in javascript) onto myArray. You can see this because if you just don't set currentRowData.length = 0 it works fine.

    I think you thought that you would use currentRowData as a temporary array to build up the second dimension and you thought that it would not go out of scope, so you had to reset it before the end of the array. That is not the case - it get's redefined each time you iterate through the for loop.
    -ChaCha

  3. #3
    Web-coding NINJA! silver trophy beetle's Avatar
    Join Date
    Jul 2002
    Location
    Dallas, TX
    Posts
    2,900
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Excellent explanation, Cha Cha

    I humbly submit this copy method for Array, which can be handy at times.
    HTML Code:
    <script type="text/javascript">
    /*  Return copy of array
    ------------------------------------------- */
    Array.prototype.copy = function()
    {
    	var copy = [];
    	for ( var i = 0; i < this.length; i++ )
    	{
    		copy[i] = ( typeof this[i].copy != 'undefined' )?
    			this[i].copy():
    			this[i];
    	}
    	return copy;
    }
    </script>
    beetle a.k.a. Peter Bailey
    blogs: php | prophp | security | design | zen | software
    refs: dhtml | gecko | prototype | phpdocs | unicode | charsets
    tools: ide | ftp | regex | ffdev




  4. #4
    ********* Ornithologist AtomicPenguin's Avatar
    Join Date
    May 2002
    Location
    Vancouver, BC
    Posts
    459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    [edit]

    Ahh.. that makes sense - thanks Chacha!

    I'll try out that code you suggested, Beetle. Much appreciated.

    [Also: I guess what I could do is just dump the second array altogether and manually push a [i + "_1", i + "_2"] onto myArray - that would get around it, too. ]

    Thanks for the help, everyone!

  5. #5
    Web-coding NINJA! silver trophy beetle's Avatar
    Join Date
    Jul 2002
    Location
    Dallas, TX
    Posts
    2,900
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Cha Cha

    I just read your explanation again and, as good as I think it is, I disagree with something.

    To the best of my knowledge, javascript doesn't automatically dereference non-primitives when the push() method is used. The reference survives until the reference variable is deleted, redeclared, or falls out of scope.
    Code:
    var arr = [1,2];
    var arr2 = [3];
    
    arr.push( arr2 );
    arr2.push( 4 );
    
    alert( arr ); // 1,2,3,4
    Since the first step of each loop redeclares the array, it is dereferenced at this moment, and not when pushed.

    And I'd like to follow up on something we both mentioned only in part: Javascript passes everything by reference except the primitive types: String, Number, Boolean, undefined, and null -- even though the latter is typeof object.
    beetle a.k.a. Peter Bailey
    blogs: php | prophp | security | design | zen | software
    refs: dhtml | gecko | prototype | phpdocs | unicode | charsets
    tools: ide | ftp | regex | ffdev




  6. #6
    SitePoint Addict
    Join Date
    Mar 2003
    Location
    CA
    Posts
    210
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    javascript doesn't automatically dereference non-primitives when the push() method is used
    I meant that whenever you call a method of the object the object itself must be dereferenced (in order to get at the object so the method can be found). Of course the object being pushed ONTO the stack isn't dereferenced. That would imply creating a new copy of the object and he wouldn't be experiencing this problem. It is precisely because js doesn't dereference the object when it is pushed onto the stack that is causing his confusion. That is all. Don't you think that this sort of mixup happens to js coders who never learned a lower level language and, hence, have no real first-hand experience with references? They can definitely be tricky this way
    -ChaCha

  7. #7
    Web-coding NINJA! silver trophy beetle's Avatar
    Join Date
    Jul 2002
    Location
    Dallas, TX
    Posts
    2,900
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Indeed =)
    beetle a.k.a. Peter Bailey
    blogs: php | prophp | security | design | zen | software
    refs: dhtml | gecko | prototype | phpdocs | unicode | charsets
    tools: ide | ftp | regex | ffdev





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
  •