[Javascript] How do different browsers handle arrays?

SineCosine

I'm still looking for my Tangent
Reaction score
77
I made this blog dedicated to providing information about a music game.
There is a section with the game's Song List.

The Song List contains the following information:
  • Artist Name
  • Song Name
  • Location
  • Single (A difficulty type)
  • Double (A difficulty type)
  • Single Performance (A difficulty type)
  • Double Performance (A difficulty type)

And so, I have 7 arrays each storing their respective data.
Each array element has a method (Do you call it that?) 'index' that tells them what their index is.

Users can choose to select to sort the song list according to:
  • Artist Name
  • Song Name
  • Location
  • Single (A difficulty type)
  • Double (A difficulty type)
  • Single Performance (A difficulty type)
  • Double Performance (A difficulty type)

When they click a button, it calls a function that copies that array into a variable using the [ljass]array.concat()[/ljass] method.
Then, it sorts and passes the copied&sorted array into a different function that draws the table according to the sorted array.

That table drawing function is the problem here.
[ljass]function drawTable (arraySource)[/ljass]

At some point, I need to reference arraySource.
  • fromSource.length
  • fromSource[loop].index

It works fine in Mozilla Firefox.
However, in Google Chrome, I get a blank error message with the [ljass]try {} catch(e) { alert(e); }[/ljass] approach.

But I am guessing that fromSource is undefined in Chrome.
So, I would like to know if anyone knows the proper way to handle arrays across all browsers =x


-tl;dr Version-
I can't pass an array variable into a function in Chrome.
I can with Firefox.

Help me.
 

Magentix

if (OP.statement == false) postCount++;
Reaction score
107
Try logging the 'instanceof' property of the variable you pass as an argument.
I got a hunch that Chrome thinks it's an Object instance, while FF thinks it's an Array instance.

Edit:
Also, how do you create your arrays?
Whether you use the literal ([]) or the object (new Array()) can make a difference as well.
 

tooltiperror

Super Moderator
Reaction score
231
Try logging the 'instanceof' property of the variable you pass as an argument.
I got a hunch that Chrome thinks it's an Object instance, while FF thinks it's an Array instance.

Edit:
Also, how do you create your arrays?
Whether you use the literal ([]) or the object (new Array()) can make a difference as well.

I've always heard that new Array is the better alternative, for cross browser support.
 

Magentix

if (OP.statement == false) postCount++;
Reaction score
107
I've always heard that new Array is the better alternative, for cross browser support.

Nah, they do exactly the same in 'normal circumstances'.
Browsers that don't support literals date back to Netscape 2 or 3...

However, if you redefine Array (by accident or willingly), [] still returns an array, while new Array() will not.
 

JerseyFoo

1/g = g-1
Reaction score
40
Give us ze code.

Chrome treats all arrays as objects internally. And I'm fairly sure modern browsers are supposed to force Object type if...
  • You use a string key.
  • You store objects in the array.
  • You use a number that becomes a string key.

For that last one I mean this...
Code:
var arr = [];
arr.push( 1 );
arr.push( 2 );
arr[9001] = 3;

Also; slice and splice work just as nice as concat.
 

SineCosine

I'm still looking for my Tangent
Reaction score
77
I apologize for not answering sooner,
I kinda'... Dozed off..

Anyways, I'll try and get only the important bits in.. ><
And I apologize for using capital letters as variable names =x
A habit I have yet to get rid of ><

Code:
                        var Songs = [];
                        //I have some functions and shit that add string-variables to this array

			function titleSort () {
                                //User clicks the 'Title' button and it calls this function
                                //Ignore the useless 'test' and .pop(), I was still an idiot, I see I've forgotten to change this xD
                                //I know my mistake, I'll fix it later, I gotta' go out in half-an-hour ><
				var temp_Song = Songs.concat('test');
				temp_Song.pop();
				temp_Song.sort();
				drawTable(temp_Song, 0);
                                //The reason I don't pass 'Songs' to the drawTable() function and then let drawTable() create a local copy is because the array passed can contain either numbers or strings
			}

			function drawTable (fromSource, chartType) {
                                //Don't comment about how I can just use .insertRow() and .insertCell()
                                //I only realized that after I completed everything ><
                                //I'll change it when I have time, It works on Mozilla, I am happy with that for now =x
				var T = document.getElementById('List'); //List is a table element
				T.innerHTML = '  '; //Lazy man's way of removing any previous tables inside the table
				var R = document.createElement('tr');
				R.style.fontSize = '0.7em';
				R.style.fontWeight = 700;
				var D = document.createElement('td');

				D.innerHTML = 'Artist Name';
				R.appendChild(D);	

				D = document.createElement('td');
				D.innerHTML = 'Song Name';
				R.appendChild(D);		

				D = document.createElement('td');
				D.innerHTML = 'Location';
				R.appendChild(D);
                                //Um..
                                //Ignore the ugly code over here, problem is further down
				if (chartType == 0) {

					D = document.createElement('td');
					D.innerHTML = 'Single';
					R.appendChild(D);		

					D = document.createElement('td');
					D.innerHTML = 'Double';
					R.appendChild(D);		

					D = document.createElement('td');
					D.innerHTML = 'Single Performance';
					R.appendChild(D);

					D = document.createElement('td');
					D.innerHTML = 'Double Performance';
					R.appendChild(D);

				} else if (chartType == 1) {
					D = document.createElement('td');
					D.innerHTML = 'Single';
					R.appendChild(D);	
				} else if (chartType == 2) {
					D = document.createElement('td');
					D.innerHTML = 'Double';
					R.appendChild(D);	
				} else if (chartType == 3) {
					D = document.createElement('td');
					D.innerHTML = 'Single Performance';
					R.appendChild(D);	
				} else if (chartType == 4) {
					D = document.createElement('td');
					D.innerHTML = 'Double Performance';
					R.appendChild(D);	
				}

				T.appendChild(R);

				var loop = 0;
				var S;
				var doIAdd;

                                //Here, is where it all starts
                                //I added a try {} catch(e) {alert(e);} here, no errors for Mozilla, an 'object Error' here
                                //I tried alert(fromSource), gave me 'undefined'
				while (loop < fromSource.length) {
                                if (fromSource[loop]) {
					R = document.createElement('tr');
					R.style.fontSize = '0.7em';
					D = document.createElement('td');
					S = fromSource[loop].key;
					doIAdd = 0;


					D.innerHTML = artist[S];
					R.appendChild(D);	

					D = document.createElement('td');
					D.innerHTML = Songs[S];
					R.appendChild(D);		
	
					D = document.createElement('td');
					if (type[S] == 0) {
						D.innerHTML = 'Arcade';
					} else if (type[S] == 1) {
						D.innerHTML = 'Remix';
					} else if (type[S] == 2) {
						D.innerHTML = 'Full';
					} else if (type[S] == 3) {
						D.innerHTML = 'Short Cut';
					} else if (type[S] == 4) {
						D.innerHTML = 'Skill Up Zone';
					} else if (type[S] == 5) {
						D.innerHTML = 'Mission Zone';
					}
					R.appendChild(D);

					if (chartType == 0) {
	
						D = document.createElement('td');
						D.innerHTML = single[S];
						if (D.innerHTML == '') {
							D.innerHTML = '&nbsp;';
						}
						R.appendChild(D);		
	
						D = document.createElement('td');
						D.innerHTML = dbl[S];
						if (D.innerHTML == '') {
							D.innerHTML = '&nbsp;';
						}
						R.appendChild(D);		
	
						D = document.createElement('td');
						D.innerHTML = sp[S];
						if (D.innerHTML == '') {
							D.innerHTML = '&nbsp;';
						}
						R.appendChild(D);

						D = document.createElement('td');
						D.innerHTML = dp[S];
						if (D.innerHTML == '') {
							D.innerHTML = '&nbsp;';
						}
						R.appendChild(D);
						doIAdd = 1;

					} else if (chartType == 1 && single[S]) {
						D = document.createElement('td');
						D.innerHTML = single[S];
						if (D.innerHTML == '') {
							D.innerHTML = '&nbsp;';
						}
						R.appendChild(D);
						doIAdd = 1;		
					} else if (chartType == 2 && dbl[S]) {
						D = document.createElement('td');
						D.innerHTML = dbl[S];
						if (D.innerHTML == '') {
							D.innerHTML = '&nbsp;';
						}
						R.appendChild(D);
						doIAdd = 1;			
					} else if (chartType == 3 && sp[S]) {
						D = document.createElement('td');
						D.innerHTML = sp[S];
						if (D.innerHTML == '') {
							D.innerHTML = '&nbsp;';
						}
						R.appendChild(D);
						doIAdd = 1;			
					} else if (chartType == 4 && dp[S]) {
						D = document.createElement('td');
						D.innerHTML = dp[S];
						if (D.innerHTML == '') {
							D.innerHTML = '&nbsp;';
						}
						R.appendChild(D);	
						doIAdd = 1;		
					}
		
					if (doIAdd > 0) {
						T.appendChild(R);
					}

					loop = loop + 1;
                                }
				}

			}

[EDIT]
@Megentix
I define arrays with ([]), is that bad?
And I've never used instanceof =x

I tried: [lJASS]alert(fromSource instanceof Object);[/lJASS] and got "true"

I tried it for "instanceof Array" and got "true" as well ._.

[EDIT=2]
This was done on Chrome.
Didn't check what happens if I do it on Mozilla Firefox
 

JerseyFoo

1/g = g-1
Reaction score
40
This would come in handy for you...
PHP:
// There's actually a faster alternative using cloneNode but thats comparably mad science...
function newElement(e, t){
    var e = document.createElement(e);
    if (t) e.appendChild( document.createTextNode(t) );
    return e;
}

PROTIP:
PHP:
var endl = '&nbsp;';  // global
...
D.innerHTML = sp[S] || endl;

Consider this...
PHP:
			var endl = '&nbsp;';
			var eles = [];
			function get(id){
				return eles[id] || (eles[id] = document.getElementById(id)) || false;
			}
			
			
			function newElement(e, t){
				var e = document.createElement(e);
				if (t) e.appendChild( document.createTextNode(t) );
				return e;
			}
			
			// A fix.
			function enumType(arr){
				var types = ['Arcade','Remix','Full','Short Cut','Skill Up Zone','Mission Zone'];		
				for(var n in type){
					arr[n] = types[arr[n]];
                                }
                                return arr;
			}
			type = enumType(type);		
			
			
			function titleSort () {
                                //User clicks the 'Title' button and it calls this function
                                //Ignore the useless 'test' and .pop(), I was still an idiot, I see I've forgotten to change this xD
                                //I know my mistake, I'll fix it later, I gotta' go out in half-an-hour ><
				var temp_Song = Songs.concat( ['test'] );
				temp_Song.pop();
				temp_Song.sort();
				drawTable(temp_Song, 0);
                                //The reason I don't pass 'Songs' to the drawTable() function and then let drawTable() create a local copy is because the array passed can contain either numbers or strings
			}
			
			function drawTable (fromSource, chartType) {
                                //Don't comment about how I can just use .insertRow() and .insertCell()
                                //I only realized that after I completed everything ><
                                //I'll change it when I have time, It works on Mozilla, I am happy with that for now =x
				var T = document.getElementById('List'); //List is a table element
				var R = newElement('tr');
				var n;
				
				get('List').innerHTML = '  '; //Lazy man's way of removing any previous tables inside the table
				R.style.fontSize = '0.7em';
				R.style.fontWeight = 700;
				
				var labels = [
					,['Artist Name', artist]
					,['Song Name', Songs]
					,['Location', type]
				];
				var charts = [
					,['Single', single]
					,['Double', dbl]
					,['Single Performance', sp]
					,['Double Performance', dp]
				];
				
				
				var D = document.createElement('td');
				if (chartType == 0){
					labels.concat( charts );
				} else {
					labels.push( charts[chartType - 1] );
				}

				for ( n in labels ){
					R.appendChild( newElement('td', labels[n][0]) );
				}
				
				get('List').appendChild(R);

				var loop = 0;
				var S;

                                //Here, is where it all starts
                                //I added a try {} catch(e) {alert(e);} here, no errors for Mozilla, an 'object Error' here
                                //I tried alert(fromSource), gave me 'undefined'
				while (loop < fromSource.length) {				
					if (!fromSource[loop]) continue;
					S = fromSource[loop].key
					
					if ( chartType > 0 && !labels[S][labels.length-1] ) continue; // doIAdd replacement, you don't need this though.
					
					R = newElement('tr');
					R.style.fontSize = '0.7em';
					for ( n in labels ){
						R.appendChild( newElement('td', labels[n][1][S] || endl) );
					}

					get('List').appendChild(R);
				}

			}

I didn't see anything wrong with the code besides that 'test' isn't an array and your doIAdd stuff would actually result in the 'nbsp' never being applied. Writing off-hand here so there's probably a mistake here or there.
 

Magentix

if (OP.statement == false) postCount++;
Reaction score
107
For the problem at hand:
Code:
S = fromSource[loop].key

You access the array as if it were an object.
Remember: there is no such thing as associative arrays in JavaScript.

@TooltipError: The nb in nbsp stands for non-breaking, if you replace that with <br />, you kill off the effect of using nbsp :)
 

JerseyFoo

1/g = g-1
Reaction score
40
&nbsp; has nothing to do with <br/>, he's just filling empty table cells. Ah, just noticed you were referring to my code, thats a contextual mistake on my part.
 

SineCosine

I'm still looking for my Tangent
Reaction score
77
@TTE
Yea, just filling empty space =x

@JerseyFoo
I've got a lot of questions =x
I have yet to try out the code because there's so much I don't understand ><
PHP:
            var eles = [];
            function get(id){
                return eles[id] || (eles[id] = document.getElementById(id)) || false;
            }

            /*
            variable id is a String, right?
            So, how would eles[id] work? I thought we would need to use a number for array indexes? =x
            Or are we allowed to use strings as indexes as well? o.0

            [EDIT]
            Wait-
            Megentix said, "there is no such thing as associative arrays in JavaScript."
            Isn't doing (blah['name'] = something;) associative arrays? o.0
            /*

PHP:
            function enumType(arr){
                var types = ['Arcade','Remix','Full','Short Cut','Skill Up Zone','Mission Zone'];        
                for(var n in type){
                    arr[n] = types[arr[n]];
                                }
                                return arr;
            }
            type = enumType(type); 

            /*
                        This, I totally do not understand ><

                        What does 'type=enumType(type) mean' ? o.0
                        Why is it outside of any function?
                        When was it defined? =x

                        I am guessing that 'fot(var n in type)' is the more efficient replacement for my current way of looping through arrays =x

                        Umm..
                        Let's say n = 0,
                        arr[0] = types[arr[0]];

                        I truly don't understand ><
            */

Thanks for helping out ^^
I've even learned a few things from you.

@Megentix
Umm..
Is there a way around using "S = fromSource[loop].key" ?
Let's say I have a bunch of arrays.
PHP:
        var Food = [
                'Apple',
                'Almonds',
                'Amaranth leaves',
                'Barley'
        ];

        var vitaminC = [
                8.4,
                undefined,
                54.3,
                undefined
        ];

        var vitaminK = [
                4,
                undefined,
                undefined,
                0.8
        ];

        var pantothenicAcid  = [
                0.111,
                0.133,
                0.082,
                0.135
        ];

The arrays were originally empty.
I filled the arrays like this:
PHP:
        var Food = [];
        var vitaminC = [];
        var vitaminK = [];
        var pantothenicAcid = [];
        function main () {

        }

        function addFood (whatFood, mgOfC, mcgOfK, mgOfPA) {
                var i = Food.push(new String(whatFood)) - 1;
                //I use 'new String(whatFood)' instead of 'whatFood' because I can't assign Food[i].key because whatFood alone isn't an object or something ><
                Food[i].key = i;

                if (mgOfC) {
                        vitaminC[i] = new Number(mgOfC);
                        vitaminC[i].key = i;
                }
                if (mcgOfK) {
                        vitaminK[i] = new Number(mcgOfK);
                        vitaminK[i].key = i;
                }
                if (mgOfPA) {
                        pantothenicAcid[i] = newNumber(mgOfPA);
                        pantothenicAcid[i].key = i;
                }

                //in certain cases, vitaminC, vitaminK or pantothenicAcid might be given null, making it undefined.
                //Also, notice that I do not assign .key if that array's element is null/undefined
        }

        function drawTable (sourceArray, sortType) {
                /*Anyways, let's say, we sort by vitaminC,
                I would expect that we get something like:
                sourceArray = [
                        8.4,
                        54.3,
                        undefined,
                        undefined
                ];

                */

                //then, let's say we loop through this array and 'draw' the row for Foods that have vitaminC values
                //sourceArray[0].key and sourceArray[1].key will exist and be drawn
                //sourceArray[2].key and sourceArray[3].key do not exist and will not be drawn

                if (sourceArray[2].key) {
                        alert('true!');
                } else {
                        alert('false!'); //This will pop out
                }

                /*
                        The point of the .key variable is so that I can draw the tables
                        Let's just say var loop = 1
                */

                if (sourceArray[loop].key) {
                        //sourceArray[1].key exists, 
                        //sourceArray[1].key == 2

//Notice that earlier on, the Array's index would be equal to the index's key.
//But after .sort(), The index and key become totally different
                        
                        var index = sourceArray[loop].key;

                        //do stuff Food[index], vitaminC[index], vitaminK[index], pantothenicAcid[index]
                        
                }
        }

So..
Is there a better way to do it? o.0

[EDIT]
So, the problem here is that I try and access fromSource like an object by using Array[index].variable?
 

Magentix

if (OP.statement == false) postCount++;
Reaction score
107
What I meant with the associative array bit:

Code:
var myArr = ['sup','dawg'];
alert(myArr.length); // alerts 2

myArr[2] = 'omg';
alert(myArr.length); // alerts 3

myArr['foo'] = 'bar';
alert(myArr.length); // alerts 3 because Array methods/properties only take numeric keys into account

Arrays are only arrays in JavaScript if you play by the rules.
As soon as you start freewheeling, it'll start behaving very unexpectedly.


As for your code, why not create an object instead of calling a String constructor on an integer?
Code:
var i = Food.length;
Food[i] = {'key':i};
 

SineCosine

I'm still looking for my Tangent
Reaction score
77
As for your code, why not create an object instead of calling a String constructor on an integer?
Code:
var i = Food.length;
Food[i] = {'key':i};

Oh, I'll keep the associative arrays bit in mind ^^

I don't get what '{'key':i}' is =x
It.. Creates an object? o.0
Never seen or used that before ><

And 'Food' is a String array ._.
I call a String constructor on a String ._.

[EDIT]
I should have tested before asking -______-
PHP:
<html>
	<head>
		<title>Array-Test</tile>
		<script type="text/javascript">
			var Food = [];
			function main () {
				Food[0] = {'key':3};
				alert(Food[0].key);
			}
		</script>
	</head>
	<body onload="main()">
	</body>
</html>

The only problem I see is that I don't see how to set Food[0]'s value.
I need to store two things in one array element.

A value and it's original index (Or whatever it is called, I don't speak programming ><)
However, I don't see how: [lJASS]Food[0] = {'key':3};[/lJASS] is different from: [lJASS]Food[0].key = 3;[/lJASS] =x

[EDIT=2]
I have another question..
(Unrelated to the topic at hand, But I didn't feel the need to create a thread for this)

PHP:
        //How is this:
        div.setAttribute(attributeName, value);

        //Preferable to this:
        div.attributeName = value;
 

JerseyFoo

1/g = g-1
Reaction score
40
Sorry was off the internets for a bit there. Supposedly setAttribute has better compatibility but I've never run into an instance where that was true.

Also I realized the other day I used a comma on the first line of the arrays I posted before, thats no good.

I've even learned a few things from you.
Thats the idea.

If you care about the elegance of your code, you should have all those values in separate arrays together as objects. Instead of name[X], birthdate[X], you'd have objects[X].name, objects[X].birthdate .

Code:
var person = {
    name: 'Bob';
    birthday: 'April 19th';
};
alert( person.name );
Code:
- OR -

function Person(name, birthdate){
    this.name = name;
    this.birthdate = birthdate;
}
var person = new Person('Bob', 'April 19th');
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top