0

I'm trying to learn Javascript and so I made a little code, but there is something wrong with it that I can

var array = new Array("Apple","Mangosteen","Durian","Pineapples");
...
...
function B() {
    ...
    ...
    var BP = $("<p></p>");
    BP.text("Click \"x\" on items to be removed").append("<br/>");
    for (i=0;i<array.length;i++) {
        var f = array[i];
        var F = $("<div></div>");
        F.attr({"class":"f"});
        var N = $("<span></span>");
        N.attr({"class":"n"});
        N.text(f);
        var d = $("<span></span>");
        d.attr({"class":"cc sl"});
        d.bind("click", function(e){
            e.stopPropagation();
            e.preventDefault();
            IR(f,F);
        });
        d.html("&times;");
    ...
    ...
}
function IR(f,F) {
    var a = array.indexOf(f);
    array.splice(a,1);
    F.remove();
}

When I added console.log(f); in function IR(), the value passed will always be "Pineapples", regardless if I'm clicking "x" on "Apples" or "Durian", the f value passed will always be "Pineapples". What is wrong with it?

2
  • Can you please add a fiddle? Commented Sep 8, 2016 at 8:43
  • 2
    tip: try to use proper naming in your code it will be more readable and understandable, while now who the slice know what A and B are?? Commented Sep 8, 2016 at 8:46

3 Answers 3

2

You call a function inside a for loop - something you can read more about here JavaScript closure inside loops – simple practical example.

For now, if you're using ES6. The easiest way to solve it will be using let in the for loop.

for (let i=0;i<array.length;i++) { ...... }

Or else, use Array.forEach() instead of the for loop.

In your case it should be something like

array.forEach(function(fruit) {
        var f = fruit;
        var F = $("<div></div>");
        F.attr({"class":"f"});
        var N = $("<span></span>");
        N.attr({"class":"n"});
        N.text(c);
        var d = $("<span></span>");
        d.attr({"class":"cc sl"});
        d.bind("click", function(e){
            e.stopPropagation();
            e.preventDefault();
            IR(f,F);
        });
        d.html("&times;");
    ...
    ...
});
Sign up to request clarification or add additional context in comments.

1 Comment

Calling a function in a loop is not "a well-known issue in JavaScript". You make it sound as if there's a bug in the language.
1

its because the scope of variable "i" is global, so var f = array[i]; will result in var f = array[3]; so you will get only "Pineapples". I will give you a simple sample code to understand the issue. please run below code.

    <script>
var funcs = [];
for (var i = 0; i < 3; i++) {          // let's create 3 functions
    funcs[i] = function() {            // and store them in funcs
        console.log("My value: " + i); // each should log its value.
    };
}
for (var j = 0; j < 3; j++) {
    funcs[j]();                        // and now let's run each one to see
}
</script>

you will get only 3 because "i" is in global scope.

Comments

1

When you declare a variable using var it will be declared within a scope of the function. That's why when you click 'x' javascript will pass to the IR function the last value of the variables - "Pineapples" and Pineapples's div. If you want to declare a variable within the 'for' cycle scope, use let. In this case, in every loop of 'for' cycle javascript will create a new variables f and F.

var array = new Array("Apple","Mangosteen","Durian","Pineapples");

function B() {
    var BP = $("<div></div>");
    BP.text("Click \"x\" on items to be removed").append("<br/>");
    for (var i=0;i<array.length;i++) {
        let f = array[i];
        let F = $("<div></div>");
        F.attr({"class":"f"});
        var N = $("<span></span>");
        N.attr({"class":"n"});
        N.text(f);
        var d = $("<span></span>");
        d.attr({"class":"cc sl"});
        d.bind("click", function(e){
            e.stopPropagation();
            e.preventDefault();
            IR(f,F);
        });
        d.html("&times;");
        F.append(N).append(d)
        BP.append(F)
      }
}
function IR(f,F) {
    var a = array.indexOf(f);
    array.splice(a,1);
    F.remove();
}

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.