JavaScript: returned global array variable undefined
JavaScript newbie here. I have searched and searched for answers and don't seem to figure it out. The arrays I pass to the function are not being passed as references correctly. I don't think this is an asynchronous problem like many posts have, but I could be wrong.
I have global arrays that I pass to functions. Inside the function, the arrays return their own values, but when I try to access them outside the function, they are undefined.
In context, I go through 3 arrays that maintain dry bulb temperature, wet hood temperature and hour so that measurements are taken for subsequent calculations. I've included some sample data for brevity. Sample code below:
function run(){
var hour = [];
var db = [];
var wb = [];
var cities = ["AB Edmonton","MI Detroit"];
getData(hour, db, wb, cities);
//this shows undefined, although within getData it is accurate data
alert(hour[1]);
}
function getData(hour, db, wb, cities){
//i= drop-down selection index, set to zero for testing
i=0;
switch(cities[i]) {
case "AB Edmonton":
hour = [1,2,3];
db = [15,18,21];
wb = [10,13,20];
break;
//case "MI Detroit":....
}
//this shows accurate values in the alert window
alert(cities[i] + " at hour:" + hour[i] + " the temp is:" + db[i]);
return [hour, db, wb];
};
source to share
run
assigns empty arrays hour
, db
and wb
. These are variables that are locally bound to the function run
.
It then calls getData
and passes those arrays as arguments.
Internally getData
, new local variables (also called hour
, db
and wb
) are declared and assigned to three empty arrays that were passed in when the function was called.
The function then ignores these values ββand overwrites them with new arrays (they have content).
Then it returns another new array that contains each of those arrays.
This brings us back to run
. The return value is getData
completely ignored, and the original arrays (which are still stored in variables hour
, db
and wb
owned run
) are available (but they are still empty).
You can:
- Manipulate existing arrays internally
getData
instead of overwriting them. (for example, ithour = [1,2,3]
can becomehour.push(1); hour.push(2); hour.push(3)
). - Use a return value
getData
(in this case, you don't have to worry about assigning values ββor passing empty arrays in the first place). You can use object instead of array so you can have useful names instead of order here.
Such:
function run(){
var cities = ["AB Edmonton","MI Detroit"];
var data = getData(cities);
alert(data.hour[1]);
}
function getData(cities){
//i= drop-down selection index, set to zero for testing
var i=0; // Use locally scoped variables where possible
var hour, db, wb;
switch(cities[i]) {
case "AB Edmonton":
hour = [1,2,3];
db = [15,18,21];
wb = [10,13,20];
break;
//case "MI Detroit":....
//this shows accurate values in the alert window
alert(cities[i] + " at hour:" + hour[i] + " the temp is:" + db[i]);
return { hour: hour, db: db, wb: wb];
};
source to share
Well, these are not global variables. One variable hour
is local to run()
, in which it is declared with var
, the other is local to getData
, in which it is declared as a parameter.
In your function, getData
you are overwriting the local variable (which initially has the value that was passed in run()
) in the line
hour = [1,2,3];
and hence the two variables refer to different arrays.
source to share
function getData(hour, db, wb, cities){ }
hour
, db
etc. are references to initial arrays.
When you write hour = [1,2,3];
, local references hour
do not indicate more on your desired array, and a new array that you just created: [1,2,3]
. To fix this problem, just hours.push(1,2,3);
put values ββin the parameters
so that you don't overwrite your links.
This is the same problem that comes up when you do:
a = {x : 1};
function setX(obj) {
obj = {x: 2};
}
function correctSetX(obj) {
obj.x = 2;
}
The function will setX
do nothing, but correctSetX
will match a in {x : 2}
.
source to share
Thanks everyone for your help! I posted how I edited my code to make it work based on comments. A couple of things:
- I moved all the variables to the local getData () function. At least one of the comments gave the impression that it is better to save variables locally (forgive me, I'm not a CSE guy, but I appreciate the advice and patience on your behalf).
-I couldn't just use the .push method because the amount of data generated the error. (there are at least 8760 measurements per year) I can't remember the exact error, but it was related to stack limits
- In Quentin's suggestion, I created a dataSet object instead that had array properties. This object is what the getData function returns. Thanks again, this was a much better way to handle this.
Example below (with limited data):
function run(){
//get data
var dataSet = getData();
//test the result on the 2 hour reading
alert(dataSet.hour[1]);
}
function getData(){
//i= drop-down selection index, set to zero for testing
var i=0;
var hour,db,wb;
var cities = ["AB Edmonton","MI Detroit"];
switch(cities[i]){
case "AB Edmonton":
hour = [1,2,3];
db = [10,11,12];
wb = [13,14,15];
break;
//case "MI Detroit":...
} //end of switch
return {hour: hour, db: db, wb: wb};
}; //end of getData
source to share