1

I have a list of elements, performing a function on each. Said function results in a subtotal which I wish to add to a grand total. Since I prefer to keep the window as unabused as possible, I declared the variable in my script right before the list declaration.

var total = 0;
$.each($("input[flag]:checked"), function(index, value){
  var sub =+ value.attributes["blipp"].value;
  total += sub; // this is window.total not my total!
});

I do remember that the scoping in JavaScript is less than well design, so I expected something unwanted to happen. And so I was right. The question is if it's possible to enclose the variable somehow and still keep it accessible form the individual function calls.

Konrad Viltersten
  • 36,151
  • 76
  • 250
  • 438

2 Answers2

2

So many ways to do this, but a common one would be to wrap all of it in another function:

function total(){
    var total = 0;
    $.each($("input[flag]:checked"), function(index, value){
    var sub =+ value.attributes["blipp"].value;
    total += sub; 
    });        
    return total;  
}
Robert Moskal
  • 21,737
  • 8
  • 62
  • 86
1

You can create a scope with a IIFE, Immediately Invoked Function Expression, just for that reason and do:

(function(){
    var total = 0;
    $.each($("input[flag]:checked"), function(index, value){
      total += value.attributes["blipp"].value;
    });
    // do something with total here...
})();

This way there will be a variable created in a scope that self-consumes itself.


You can also use native JavaScript and a normal function to create a new scope (altough I dont need a new variable):

function getTotal(sel) {
    var els = [].slice.call(document.querySelectorAll(sel));
    return els.reduce(function(total, input) {
        var val = input.checked ? parseInt(input.value, 10) : 0;
        return total + val;
    }, 0);
}
console.log(getTotal('input[flag]')); // 45

jsFiddle: https://jsfiddle.net/2s64cjrp/

Community
  • 1
  • 1
Sergio
  • 28,539
  • 11
  • 85
  • 132
  • Will the function be invoked without an explicit call? – Konrad Viltersten Jan 13 '16 at 21:52
  • @KonradViltersten yes. It gets invoked "automagically" since we add `()` in the end of `(function(){})` – Sergio Jan 13 '16 at 21:55
  • Also, I've always wondered - shouldn't it be the same as skipping the function keyword and putting my stuff doing this: *({my-stuff-here})();*? What kind of functionality is **not** being invoked if we skip the function thingy? – Konrad Viltersten Jan 13 '16 at 22:01
  • @KonradViltersten inside that IIFE the scope is new and will not go out. You can do some stuff like `(alert(10))()` without the keyword `function`, but I would not do it. Also if you need multiline and `;` it will break – Sergio Jan 13 '16 at 22:03
  • 1
    Forget it. I just saw that it's a link under *IIFE*. Once I read that answer, everything is Amazing Grace now ("*...I was blind and now I see...*"). +1 for that. – Konrad Viltersten Jan 13 '16 at 22:04
  • @KonradViltersten nice. I added a new example also, in case its usefull. Such IIFE are really nice for not poluting global scope. – Sergio Jan 13 '16 at 22:16