2

This code works fine -- clicking first (li) yields "0" and clicking second (li) yields "1".

$("li").eq(0).click(function () { alert(0) });
$("li").eq(1).click(function () { alert(1) });

However, I'd rather use a for loop. With the following, each (li) yields "2".

for (var i = 0; i < 2; i++) {
            $("li").eq(i).click(function () { alert(i) });
        }

Why? Thanks in advance. Apologies if this is something obvious, but it's driving me crazy.

1
  • 1
    why not just do $("li").click(function(){ alert($(this).index()) }); Commented Jan 26, 2013 at 22:30

4 Answers 4

2

Much simpler to use jQuery index() method which requires no for loop:

$('li').click(function(){ 
   /* "this " is element clicked*/       
    alert( $(this).index() );
});

Using index() with no arguments will return the index of element with relation to it's siblings. There also are ways to use index() for other collections of elements as well

API refrence: http://api.jquery.com/index

Sign up to request clarification or add additional context in comments.

2 Comments

That may work, but what if the for loop does other things outside of the scope of this. I think he was trying to figure out why the variable wasn't "sticking" so to speak, not because he actually wants to alert the index of the LI.
@HighParkCoder that is certainly an opinion, personally I believe OP will benefit from this knowledge and code simplification. regardless of other functionality within loop, relationship shown by OP is identical to index()
2

This is called closure. When you do this, you are setting a global variable called i. So, when you click it, your click function remembers this variable which is always 2 as it is its value at the end of the loop.

Now why is it a globa variable?, because javascript has function scop instead of block scope

<script type="text/javascript">
    var imGlobal = "Hello!";
    // ^ Watch out for the scope! I'm NOT inside a function

    for (var i = 0; i < 2; i++){}
    // ^ Watch out for the scope! I'm NOT inside a function EITHER!!!

    function(){
        // ^ Watch out for the scope! I'm inside a function
        var imNOTGlobal = "I won't exist after the function has returned (under certain circumstances ;])";
    }();
    console.log(imGlobal);    //"Hello!"
    console.log(i);           //2
    console.log(imNOTGlobal); //undefined
</script>

Closure is a way of javascript to do useful things like this:

// To get the nth prime number
var getPrimeNumber = function (){
    var primeNumbers = [];
    return function(n){
        if(!primeNumbers[n]){
            // Calculate the nth prime number and insert it into the array.
        }

        return primeNumbers[n];
    };
}(); // The function is executed immediately 
// making "var getPrimeNumber" to hold the result of the execution 
// which is a function that remembers primeNumbers 
// and is who does the actual calculation

getPrimeNumber(1);
getPrimeNumber(2);
getPrimeNumber(3); // Calculate it the first time
getPrimeNumber(4);
getPrimeNumber(3): // This is already calculated!
// The array ends up with 4 slots;    

Everytime you call the function, it will check if it has already calculated the nth prime number and store it in an array which is accessible for the closure, this way you don't have to calculate everytime the function is asked the nth number.

Now, what is useful about this?: You get to use a variable that is not initialized everytime you call getPrimeNumber();and this variable is NOT a global object.

Note: The function doesn't work, but illustrates the point.

2 Comments

Closure is a way of javascript to do useful things like this: ...like what?
@HighParkCoder Sorry, it went in without the rest :S
1

the variable i is a global variable. After the for loop it has a value of 2, and every time you click on any li element, it is alerting the value of i, which is now 2.

Try:

for (var i = 0; i < 2; i++) {
   $('li').eq(i).click(function() { 
         alert( $(this).index() ); 
    });        
}

Comments

0

Closure is a bitch :) You should do something like this - this will capture the "correct" i

function createAlertFunction(i) {
    return (function onClickFunc () {
        alert(i)
    });
}

for (var i = 0; i < 2; i++) {
    $("li").eq(i).click = createAlertFunction(i);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.