0

I am trying to pass an array that I have saved as a var. I declare the var in the parent function and add the arr as an argument in the parent function. Then I am pulling in the arr as an argument inside the callback invocation. The console tells me that linksA is undefined.

var supportLists = function(selector, arr) {
    var parentList = document.getElementById(selector);
    var theList = parentList.querySelectorAll("a");

    var linksA = [
        "http://www.example.com",
        "http://www.example.com/path2",
        "1",
        "2",
        "4",
        "3",
        "5",
        "6",
        "7"
    ];

    var linksB = [
        "1",
        "2",
        "3"
    ];

    var linksC = [
        "1",
        "2",
        "3",
        "4",
        "5",
        "6",
        "7",
        "8",
        "9",
        "10",
        "11",
        "12"
    ];

    var linksD = [
        "1",
        "2"
    ];

    var linksE = [
        "1",
        "2",
        "3"
    ];

    var linksF = [
        "1",
        "2",
        "3",
        "4",
        "5",
        "6"
    ];

    var linksG = [
        "1",
        "2",
        "3"
    ];

    var linksH = [
        "1",
        "2",
        "3",
        "4"
    ];

    var linksI = [
        "1"
    ];

    var linksJ = [
        "1",
        "2",
        "3",
        "4",
        "5"
    ];

    function processLi(listItems, links) {

        for (var i = 0; i < links.length; i++) {

            listItems.forEach(function(item, index) {
                item.href = links[index];
                item.target = "_blank";

            });

        }
    }

    processLi(theList, arr);
};

supportLists("support-list", linksA);
supportLists("support-list-b", linksB);
supportLists("support-list-c", linksC);
supportLists("support-list-d", linksD);
supportLists("support-list-e", linksE);
supportLists("support-list-f", linksF);
supportLists("support-list-g", linksG);
supportLists("support-list-h", linksH);
supportLists("support-list-i", linksI);
supportLists("support-list-j", linksJ);
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
ardev
  • 653
  • 2
  • 6
  • 19
  • 3
    You're trying to use those `links` variables outside the function where they're declared. –  Sep 15 '16 at 17:13
  • 2
    Adding to @squint answer, you could declare the arrays on the same scope on which the function will be called and pass them as arguments for the function, or also pass the name of the links array to be used as an input parameter for the function and have a logic inside it to select and use the right array. – GCSDC Sep 15 '16 at 17:17
  • get the same error if I put them in the processLi function. besides, arent I using them in the invocation which is sitting inside the parent function, not the callback? – ardev Sep 15 '16 at 17:19
  • 1
    I have no idea what this had to do with higher-order functions. – Bergi Sep 15 '16 at 17:19
  • 1
    @ardev You're supposed to put them *outside* of the `supportLists` function, next to the calls that use the variables – Bergi Sep 15 '16 at 17:20
  • You're also going to discover that `listItems` doesn't have a `.forEach()` method, but that's a separate issue. –  Sep 15 '16 at 17:21
  • @bergi, thanks for pointing that out -- doesnt have anything to do with higher-order functions...scope or callback function wouldve been a better tag. – ardev Sep 15 '16 at 18:19
  • @squint because querySelectorAll returns a NodeList, however it worked as written in this post. Just to be safe, I switched in `[ ].forEach.call(listItems, function(){` – ardev Sep 15 '16 at 18:39
  • Strange. The `.forEach` shouldn't work on a NodeList unless `NodeList.prototype` has been extended with iterator methods. –  Sep 15 '16 at 18:49

2 Answers2

1

If you want to use a variable it has to be available in the scope where you want to use it or pass it (to a function), which means that it has to be declared in that scope or in a parent scope.

Since you are passing the arrays to the supportLists function you have to declare them outside that function.

If you move all the array declarations outside the function your code would look something like this (I have added a few comments to show where a scope begins and where it ends)

// This is the 'parent' scope (probably the global/window scope in your case)

var linksA = [
    "http://www.example.com",
    // ...
];

// ...

var linksJ = [
    "1",
    "2",
    "3",
    "4",
    "5"
];

var supportLists = function(selector, arr) {
    // Here begins the 'supportLists' function scope
    // The 'supportLists' function has access to this scope and the 'parent' scope
    var parentList = document.getElementById(selector);
    var theList = parentList.querySelectorAll("a");

    function processLi(listItems, links) {
        // Here begins the 'processLi' function scope
        // The 'processLi' function has access to this scope, the 'supportLists' scope and the 'parent' scope

        for (var i = 0; i < links.length; i++) {

            listItems.forEach(function(item, index) {
                // Here begins the 'function(item, index)' function scope
                // The 'function(item, index)' function has access to this scope, the 'processLi' scope, the 'supportLists' scope and the 'parent' scope

                item.href = links[index];
                item.target = "_blank";
            });// Here ends 'function(item, index)' function scope
            // Back in the 'processLi' function scope
        }
    } // Here ends the 'processLi' function scope
    // Back in the 'supportLists' function scope

    processLi(theList, arr);
}; // Here ends the 'supportLists' function scope
// Back in the 'parent' scope

supportLists("support-list", linksA);
supportLists("support-list-b", linksB);
supportLists("support-list-c", linksC);
supportLists("support-list-d", linksD);
supportLists("support-list-e", linksE);
supportLists("support-list-f", linksF);
supportLists("support-list-g", linksG);
supportLists("support-list-h", linksH);
supportLists("support-list-i", linksI);
supportLists("support-list-j", linksJ);
Ma3x
  • 5,761
  • 2
  • 17
  • 22
  • Thanks, this worked. Just for discussion, shouldnt the var have been scoped for the callback given that the vars were defined within the parent scope the callback should have inherited? – ardev Sep 15 '16 at 18:41
  • @ardev: in your original code the array variables were defined inside the `supportLists` function scope (not the 'parent'/global scope), however you were trying to use them inside the global scope where those array variables were not available/declared. See this answer for JS scope examples: http://stackoverflow.com/questions/500431/what-is-the-scope-of-variables-in-javascript – Ma3x Sep 15 '16 at 18:57
0

At present, your variables are defined in local scope so they are not visible to code outside supportLists function.

Solution:

Define the variables outside the function. Example,

var linksB = ["1", "2", "3"];
var supportLists = function(selector, arr) {  //YOUR CODE  }
Amber Beriwal
  • 1,568
  • 16
  • 30
  • #2 is not a solution at all. You'd need to call the function to create the variables before you call it with the variable as an argument. Also, global variables are evil. – Bergi Sep 15 '16 at 18:35