3

I have a function like so:

var eatLunch = (function () {
    var sandwiches = [$("#sand1"), $("#sand2")];

    return function (eaten) {
        for (var i = 0, len = eaten.length; i < len; i++) {
            sandwiches[i].attr("class", "eaten-by " + eaten[i].by)
        }
    };
}());

eatLunch([
    {
        result: "good",
        by: "Adam"
    },
    {
        result: "meh",
        by: "Adam"
    }
]);

The intention is to cache the dom elements #sand1 and #sand2 in a closure to reduce the number of dom touches this function has to make. Without closure, the elements have to be assigned to variables every time I call the function.

However, the attr method does not seem to work. Upon further inspection, sandwiches[i] is defined, and it has the attr method. The function does not throw an error, it just keeps looping, but the dom elements do not get updated.

If I move sandwiches into the local scope, it works perfectly, but this is more expensive. See below:

var eatLunch = function (eaten) {
    var sandwiches = [$("sand1"), $("sand2")];

    for (var i = 0, len = eaten.length; i < len; i++) {
        sandwiches[i].attr("class", "eaten-by " + eaten[i].by)
    }
};

eatLunch([
    {
        result: "good",
        by: "Adam"
    },
    {
        result: "meh",
        by: "Adam"
    }
]);

What's going on here?

2 Answers 2

1

You're probably running your code before the DOM is loaded.

Move it to the bottom of the page.

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

2 Comments

I think this was it. The function is defined before those elements are present, as the page content is loaded in through ajax.
That did it. I refactored my code to define the variables in the closure, but not assign them. Then every time the eatLunch gets called I check if sandwiches.length is 0. If so, I assign the dom elements to sandwiches. That way I only pay for the dom touches the first time the function is called.
1

var i = 0, var len = eaten.length;

Don't use var in the second one. Write:

var i = 0, len = eaten.length;

You also need to change eaten.by to eaten[i].by

Minor errors are a pain to find.

Live Fixed Example

4 Comments

This doesn't explain why his second example works. I wonder if this is really his real code.
@Slaks I tried his second example, it's broken :\
This is just an illustrative example. This is a simplified version. The errors you mentioned were typos in the example. I have updated them. Sorry for the confusion.
@Adam then we need actual code. As you can see your example works in my fiddle. Your bug is more complex then what you have supplied us.

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.