1

I have array this.conds = ["addr", "acc"] for example. I have all these DOM objects in html tree. All for this piece of code:

     for(cond in this.conds) {

        this.searchBy[this.conds[cond]] = {
            "btn": $("#" + this.conds[cond] + "Btn"),
            "fields": $("#" + this.conds[cond] + "Fields"),
            "active": false
        };

        // Handlers
        __THIS = this;
        this.searchBy[this.conds[cond]].btn.click(function() {

            __THIS.setAllUnactive();
            __THIS.searchBy[__THIS.conds[cond]].active = true;
            __THIS.searchBy[__THIS.conds[cond]].fields.show();

        });

    }

I cant make handler to handle current element of this.conds. It handle last element every time. How to avoid this wrong behavior?

Neka
  • 1,574
  • 4
  • 22
  • 36
  • why cant you use simple loop construct ,`for(cond=0;cond – dreamweiver Mar 24 '14 at 07:36
  • `cond` before handler has numeric value (indexes of `this.conds` array), but inside handler `cond` has string value (values of `this.conds` array). How?? – Neka Mar 24 '14 at 07:37

1 Answers1

1

This is a pretty common JavaScript pitfall. JS doesn't have block context; any variables you set in a block go up to the surrounding context. You have a few options here:

  1. Use $.each() to loop, as it takes a function, and consequently keeps context.
  2. Use [].forEach(), which is similar to $.each(), but native JS. (Note: not available in older browsers.)
  3. Wrap each iteration in a function, like this

function handleCond(cond) { // put all that code here } for(cond in this.conds) { handleCond(this.conds[cond]); }

I should note that it's better not to use a for...in loop for arrays. Use $.each() or for (i=0;i<list.length;i++) instead.

EDIT: In option 3, remember to switch this.conds[cond] to plain cond.

Scimonster
  • 32,893
  • 9
  • 77
  • 89