ctesta01
ctesta01

Reputation: 959

JavaScript Library Iterators

I don't have much JavaScript experience. My question is this: When I'm writing a JavaScript library, and many of the functions I'm writing functions are meant to call each other and users can call the functions I'm defining on each other in ways I might not have predicted but are valid, how do I keep the iterators in functions that have iterating loops straight?

Do I have to come up with new names for each iterator in a for loop every time I do a for-loop just to be safe that I haven't accidentally used the same variable in two functions where one function might nest inside the other in a situation I haven't predicted or thought of?

These are just a couple examples of functions that have iteration in them. Everything I'm writing is for working with interacting with Qualtrics surveys (shown in gif examples below).

function watchSet(set, mathFunction) {
    var setSize = set.length;
    for (var i=0; i < setSize; i++) {
        set[i].down().observe("keyup", mathFunction );
    }
}
function mathSum(set, output) {
    var setTotal = 0;
    for (var j=0; j < (set.length); j++) {
        var setInputValue = parseInt(set[j].down().value, 10);
        if (isNaN(setInputValue)) { setInputValue = 0; }
        setTotal = setTotal + setInputValue;
    }
    output.value = setTotal;
}
function validateError(array, color) {
    if (color === undefined) {
        color = "pink";
    }
    color = color.concat(";");
    for (var k=0; k < array.length; k++) {
        array[k].down().setAttribute("style", "background-color: ".concat(color));
    }
    $('NextButton') && $('NextButton').hide();
}

function cellRange(startCell, endCell) {
    var r1 = /^[A-Z]/;
    var r2 = /[0-9]{1,3}$/;

    var startCellColumn = r1.exec(startCell)[0].charCodeAt(0) - 61;
    var endCellColumn = r1.exec(endCell)[0].charCodeAt(0) - 61;
    var startCellRow = parseInt(r2.exec(startCell)[0], 10);
    var endCellRow = parseInt(r2.exec(endCell)[0], 10);

    var tempRange = [];
    for (var q=startCellColumn; q<=endCellColumn; q++) {
        for (var r=startCellRow; r<=endCellRow; r++) {
            tempRange.push(q);
            tempRange.push(r);
        }
    }

    var outputRange = [];
    for (var s=0; s < tempRange.length; s+=2) {
        outputRange.push(cell(String.fromCharCode(tempRange[s]+61).concat(tempRange[s+1])));
    }
    return outputRange;
}

Gif Examples: setting equivalency-validation summing a couple cells

Upvotes: 0

Views: 63

Answers (1)

jfriend00
jfriend00

Reputation: 707516

No, you don't need unique variable names in different functions.

Variables declared with var are local to the function scope in which they are declared in. They will not and do not conflict with anything outside that scope. So, your three functions watchSet(), mathSum() and validateError() can all use var i just fine and will not conflict with each other or with any third party code outside of those functions. Local variables like this are created uniquely each time the function is run and can be referred to only from within that function.

If you did not use var to explicitly declare your loop variables, then Javascript would "implicitly" create global variables by that name and then, yes, your different functions could collide if one function doing this called another so thus they were both trying to use the same global at the same time. But, as long as your variables are declared with var and your code is in a function (thus not running at the global scope), this will not happen.

You can also run your code in strict mode (highly recommended) because then an accidential implicit global is an immediate error and the interpreter will immediately show you where the problem is.

Or use .forEach()

You can also use .forEach() on arrays and not have to create your own iteration index at all.

function watchSet(set, mathFunction) {
    set.forEach(function(item) {
        item.down().observe("keyup", mathFunction );
    });
}

Or, use let in an ES6 environment

In an ES6 environment, you can use let instead of var and the variable will be scoped to only the for loop too.

function watchSet(set, mathFunction) {
    var setSize = set.length;
    // when declaring with let in a for loop, the variable is scoped to
    // only inside the for loop
    for (let i=0; i < setSize; i++) {
        set[i].down().observe("keyup", mathFunction );
    }

    // with let in a for declaration, even another use in the same function
    // does not conflict
    // this is a completely different variable than the one above
    for (let i=0; i < setSize; i++) {
        set[i].up().observe("keyup", mathFunction );
    }
}

Upvotes: 2

Related Questions