Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript variable scope question

I'm having trouble resolving a scope issue with my javascript. I have an array, dog[] that is defined from JSON, that I need access to from inside a nested function.

function blah(json) {
 for (var u = 0; u < json[0][1][u].length; u ++ ) {
    var dog = 'k' + json[0][1][u].doggies;
    console.log(dog); // prints array of doggie strings
    $('#puppy').click(function(dog) {    // dog is passed in the function
       console.log(dog); // Syntax error, unrecognized expression: #[object Object]
       $('#' + dog).css('display, 'none');
     });
   }
 }

when I dont pass dog into the click function: i get:

 $('#puppy').click(function() {
  console.log(dog) // (12)  main.js:122k4c812e3a7275e10331000000 - this is the last value in the array - from safari console
  $('#' dog).css('display', 'none);
   }

Does anyone have any suggestions to get the array with every element passed into the click function? Or am i calling the css method incorrectly to hide those divs?

like image 294
Sachin Avatar asked Sep 17 '10 18:09

Sachin


People also ask

What is scope of variable with example?

In programming also the scope of a variable is defined as the extent of the program code within which the variable can be accessed or declared or worked with.

What is the scope of variable in JavaScript?

JavaScript variables have only two scopes. Global Variables − A global variable has global scope which means it can be defined anywhere in your JavaScript code. Local Variables − A local variable will be visible only within a function where it is defined. Function parameters are always local to that function.

Is VAR function scoped?

The main difference between keywords var and let is that variables declared using let are block-scoped, while var is function scoped.


1 Answers

Problem 1

Closures bind the entire function's scope, and not individual variables or values.

Take this code for example:

function foo() {
    var i, func;

    for (i = 0; i < 10; ++i) {
        if (i == 0) {
            func = function () {
                alert(i);
            }
        }
    }

    func();
}

foo();

You may expect foo to cause 0 to be alerted. However, the value of i has changed since the function assigned to func was created; the call to func alerts "10".

Here is another example illustrating the concept:

function foo() {
    var i = 42;

    function func() {
        alert(i);
    }

    for (i = 0; i < 10; ++i) {
        // do nothing
    }

    func();
}

foo();

Try to figure out what will be alerted, and run the code as a test.

Problem 2

The second problem is that variables are bound at the function scope (and not the block scope as you expect).

Take this code:

function foo() {
    var i;

    for (i = 0; i < 10; ++i) {
        var j = i;
    }

    alert(j);
}

foo();

You may expect this code to alert "undefined", throw a run-time error, or even throw a syntax error. However, "10" is alerted. Why? In JavaScript, the above code is translated into effectively:

function foo() {
    var i;

    var j;

    for (i = 0; i < 10; ++i) {
        j = i;
    }

    alert(j);
}

foo();

It should be more clear from this example that "10" is indeed alerted.

Solution

So how do you fix your problem? The simplest way is to change your logic: instead of attaching one event handler per dog, attack one event handler per collection of dogs. For example:

function blah(json) {
    $('#puppy').click(function () {
        var u, dog;

        for (u = 0; u < json[0][1][u].length; u++) {
            dog = 'k' + json[0][1][u].doggies;

            console.log(dog);

            $('#' + dog).css('display', 'none');
        }
    });
}

If you're interested in the "proper" transformation of your existing code (i.e. having the same behaviours, except with the bug fixed), I can give you an example of that as well. However, the solution I gave above is a much better solution and results in cleaner code.

like image 137
strager Avatar answered Oct 04 '22 20:10

strager