Passing arrays to functions

Link to the project or level: https://studio.code.org/projects/applab/qiNKTuhQ90uTqWz0PIwzHdxT1qOYAqBe_g8VT_09eBo

What I expect to happen: My student is trying to create an app which displays a bunch of info for a bunch of countries. The user will pick the region, then pick the country of interest from that region. So in this piece of code, he is trying to filter a list of every country, so that all the countries in South Asia are added to a list. He wanted to do this as a function with parameters so that the function could be reused for every region.

What actually happens: He gets this error:

WARNING: Line: 14: appendItem() list parameter value (southAsiaList) is not a array.ERROR: Line: 14: TypeError: Cannot set property ‘undefined’ of undefined

What I’ve tried: He originally tried to do this without a function by tediously filtering the country list for every region (he also wants to do GDP, flag, etc., so it was long, tedious, repetitive code).

We haven’t officially covered parameters yet, so I’m a little rusty on it. I think I can see why that error is happening, but I don’t know how to accomplish what he wants.

Here’s the code:

//Creating inital lists from data table
var countryList=getColumn("Countries and Territories","Country Name");
var regionList=getColumn("Countries and Territories","Region");

//Filtered Regions Lists
var southAsiaList=["South Asia"];


filterRegions("southAsia","South Asia");

function filterRegions (variable,place){
    for(var i=0;i<regionList.length;i++){
      if (regionList[i]==place){
        appendItem((variable+"List"),countryList[i]);
  
      }
    }
}

What is happening is you are passing a string to filterRegions for the value of variable. You then concatenate that with "List" resulting in a string. appendItem wants an Array, not a string.

There are three ways to do that two of which are not recommended as good code.

The first is to pass the array, not the name into the function. This is the right way to do it.

The second is to use eval like this appendItem(eval(variable+"List"),countryList[i]); This is a bad idea but it will work.

The third is to reference the global context like this appendItem(window[variable+"List"],countryList[i]); This is also a bad idea that works.

Why are the latter two a bad idea? Because you can pass in the name of a variable that isn’t defined. It will crash without anyone having a good idea of why. It is also very hard to figure out what it actually does because you don’t know which variables nor the types of value they hold unless you run it and stop it in that function.

1 Like

Thank you! That is so helpful! Can you give a little more detail on what you mean by “pass the array, not the name into the function”?

//Creating inital lists from data table
var countryList=getColumn("Countries and Territories","Country Name");
var regionList=getColumn("Countries and Territories","Region");

//Filtered Regions Lists
var southAsiaList=["South Asia"];


filterRegions(southAsiaList,"South Asia");

function filterRegions (variable,place){
    for(var i=0;i<regionList.length;i++){
      if (regionList[i]==place){
        appendItem(variable,countryList[i]);
      }
    }
}

When you reference the variable that holds the array in the function call the array itself is passed into the function. So in the function, variable holds the array.

You could also change the name variable to something like regions.

1 Like