简体   繁体   中英

JavaScript: global array variable returned undefined

JavaScript newbie here. I've searched and searched for answers and can't seem to figure this out. The arrays that I'm passing to a function aren't being passed as references properly. I don't think this is an async issue like many posts allude to but I could be wrong.

I have global arrays that I'm passing to a function. Inside the function, the arrays return their proper values, but when I try to access them outside of the function, they are undefined.

For context, I'm passing 3 arrays that hold the dry-bulb temperature, wet-bulb temperature, and hour that the measurements were taken for later calculations. I've only included a few sample data points 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];
};

run assigns empty arrays to hour , db and wb . These are variables which are locally scoped to the run function.

It then calls getData and passes those arrays as arguments.

Inside getData new local variables (also named hour , db and wb ) are declared and are assigned the three empty arrays that were passed when the function was called.

The function then ignores those values and overwrites them with new arrays (these ones have contents).

It then returns another new array which holds each of those arrays.

This brings us back to run . The return value of getData is ignored completely and the original arrays (which are still stored in the hour , db and wb variables that belong to run ) are accessed (but they are still empty).

You can either:

  • Manipulate the existing arrays inside getData instead of overwriting them. (eg hour = [1,2,3] may become hour.push(1); hour.push(2); hour.push(3) ).
  • Use the return value of getData (in which case you don't need to bother assigning values or passing the empty arrays in the first place). You could use an object instead of an array so you can have useful names instead of an order here too.

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];
};

Well, those aren't global variables. The one hour variable 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 getData function you are overwriting the local variable (which initially has the value that was passed in by run() ) in the line

 hour = [1,2,3];

and from thereon the two variables refer to different arrays.

function getData(hour, db, wb, cities){ }

hour , db , etc are references to the initial Arrays.

When you write hour = [1,2,3]; , the hour local references does not longer point to your desired Array, but to a new Array which you have just constructed: [1,2,3] . To fix this issue simply push values to the parameters hours.push(1,2,3); so you won't overwrite your references.

This is the same problem that occurs when you do:

a = {x : 1};
function setX(obj) {
  obj = {x: 2};
}
function correctSetX(obj) {
  obj.x = 2;
}

The setX function will do nothing, while the correctSetX will correclty a to {x : 2} .

Thank you all for your help! I've posted how I edited my code to get it to work based on the comments. A couple things:

-I've moved all variables to be local in the getData() function. At least one of the comments gave the impression that it is better practice to keep variables local (forgive me, I am not a CSE guy by training, but I appreciate the tips and patience on your behalf)

-I wasn't able to simply use the .push method because the amount of data caused an error. (there are at least 8760 measurements per year) I can't remember the exact error but it was related to stack limits

-At the suggestion of Quentin, I instead created a dataSet object that had array properties. This object is what is returned by the getData function. Thank you again, this was a much better way to handle this

Sample 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM