1

I have a little JavaScript code, that loop throw in a list, and create a slider for each element. In second, it's take an event handler, so when a slider is changed, it'll write the value in to an input.

When the for run for the first time, everything is ok, the inputs gets the values, but when i change manualy the slider, it throw an error:

Uncaught TypeError: Cannot read property 'maxValue' of undefined

The code:

for (i = 0; i < sliders.length; i++)
{
    noUiSlider.create(sliders[i].object[0], {
        start: sliders[i].start,
        step: 1,
        connect: true,
        range: sliders[i].range
    });
    sliders[i].object[0].noUiSlider.on('update', function( values, handle ) {
        if ( handle ) {
            console.debug(sliders[i]);
            sliders[i].maxValue.val(Math.floor(values[handle]));
        } else {
            sliders[i].minValue.val(Math.floor(values[handle]));
        }
    });
}

In the sliders variable i have this:

var sliders = [
            {
                "object": $('#number-of-passangers'),
                "start": [4, 6],
                "range": {
                    "min": 2,
                    "max": 15
                },
                "minValue": $("#min-passanger"),
                "maxValue": $("#max-passanger")
            },
            {
                "object": $('#cost-per-day'),
                "start": [3500, 65000],
                "range": {
                    "min": 3500,
                    "max": 65000
                },
                "minValue": $("#min-cost"),
                "maxValue": $("#max-cost")
            },
        ]
tthlaszlo
  • 435
  • 2
  • 7
  • 14
  • What does sliders contains, how we can get length using sliders.length ? nowhere it's defined in code. can you post the full code ? – Kapil Yadav Aug 26 '16 at 11:19
  • sliders is a simple variable: `var sliders = [ { "object": $('#number-of-passangers'), "start": [4, 6], "range": { "min": 2, "max": 15 }, "minValue": $("#min-passanger"), "maxValue": $("#max-passanger") }, { "object": $('#cost-per-day'), "start": [3500, 65000], "range": { "min": 3500, "max": 65000 }, "minValue": $("#min-cost"), "maxValue": $("#max-cost") }, ]` – tthlaszlo Aug 26 '16 at 11:27
  • Update the question and provide full source code. – Kapil Yadav Aug 26 '16 at 11:34

1 Answers1

1

That is because i is the index of the loop, which is incremented AFTER each iteration. Before the increment i < sliders.length is evaluated and if true, the loop body is executed. That means, after the loop has finished i == sliders.length, so sliders[i]is undefined. i resides in the outer scope of the event handler, so its value will be the same for each event handler. You need to save a local copy of it like:

.on('click', (function (idx) {
    return function (values, handle) {
        /* use idx here, instead of i*/ 
    }
 })(i));

To sum up, your Problem is caused by the scope. If you consider:

function make () {
    for (var i = 0, result = []; i < 10; i++) {
        result.push(function fxi () { console.log(i); });
    }
    return result;
}

make().forEach(function (fxi) { fxi () }) // logs 10 time »10«

That is because i is defined in the scope of make() and if one of the inner functions fxi is invoked, the definition of i is searched, which is not found within the scope of fxi, so the search goes on at the next level, make() this time, there is is found, so its value taken from there. But since the loop has incremented i up to 10 while running, its value is now 10 for each fxi.

Fiddle

philipp
  • 15,947
  • 15
  • 61
  • 106