Make js closures execute right away

I can see an issue in the following code:

var elems = {
    'elem1': 'param1fds',
    'elem2': 'paramaafds2',
    'elem3': 'paramfdsfd3fdsfds'
  };

for (var k in elems) {
  $('#' + k).click(function(e) {
  // k is always elem3 when I click on the element
  // elems[k] == 'paramfdsfd3fdsfds'

By the time the code is getting executed, k is equal elem3. How can I deal with that?

Answers:

Answer

The standard generic solution is to add an IIFE protecting your variable in a closure:

for (var k in elems) {
   (function(k){
     $('#' + k).click(function(e) {
        // k is always elem3 when I click on the
     })
    })(k);
}

As you're using jQuery, you could also use $.each:

$.each(elems, function(k){
     $('#' + k).click(function(e) {

And a third solution would be to use on and provide the data:

for (var k in elems) {
    $('#' + k).on('click', {k:k}, function(e) {  
         // use e.data.k here

In the near future, with ES6, a fourth solution will be block scoped variables using let:

for (let k in elems) {
   $('#' + k).click(function(e) {
      // k is OK
Answer
var elems = {
    'elem1': 'param1fds',
    'elem2': 'paramaafds2',
    'elem3': 'paramfdsfd3fdsfds'
  };

for (var k in elems) {
    (function(elem){
        $('#' + elem).click(function(e) {});
    })(k);
...
}
Answer

I'd argue that the modern solution to this is to do it functionally, rather than with a loop:

Object.keys(elems).forEach( function(elKey) {
    $('#' + elems[elKey]).click(function(e) {});
});

It's the same result as using an IIFE but is, I think, a little easier to follow.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.