2014-12-23 1 views
1

Я следующий код CoffeeScript:CoffeeScript делает глобальную переменную `V` в` для v в values` вызывая неправильные ссылки на события

for date of dates 
    Dom.section !-> 
     Dom.div !-> 
      Dom.text if date.attending then 'Y' else 'N' 
      Dom.onTap !-> 
       Dom.text date.id 

который преобразуется в следующий JavaScript (в соответствии с CoffeeScript. орг)

var date; 

for (date in dates) { 
    Dom.section(!function() { 
    return Dom.div(!function() { 
     Dom.text(date.attending ? 'Y' : 'N'); 
     return Dom.onTap(!function() { 
     return Dom.text(date.id); 
     }); 
    }); 
    }); 
} 

не беспокоить, что код делает именно так как я делаю использовать API хэппенинг (новый разговор приложение, для которого используется может сделать плагины в CoffeeScript) и из-за этого, вы Wouldn» Это все равно.

Я объясню это, хотя:

  • dates представляет собой массив длиной 10 с объектами в нем. Эти объекты содержат такие ключи, как id, day, year, attending.
  • Я петлю по всем датам и делаю их в так называемых «разделах» на экране.
  • Каждый раздел содержит несколько div (в приведенном выше примере есть только один, для простоты).
  • В приведенном выше надписей содержится текст. «Y», когда пользователь посещает событие, «N», когда он не является.
  • Когда пользователь нажимает («onTap'-event») на этом div, он обновляет локальное и общее хранилище (в приведенном выше примере он просто добавит некоторый текст для отладки).

Все работает, отображается правильная дата и количество посетителей в правильных разделах. Таким образом, в объекте date содержатся правильные данные.

Проблема

Проблема, которую я имею, когда я нажимаю на DIV с OnTap-события. Когда я нажимаю его, он всегда будет использовать последнюю дату, которая отображается. Итак, допустим, у меня есть даты 01-12-14 до 10-12-14. Я нажимаю на 05-12-14, он добавит идентификатор 10-12-14 в виде текста на экране. После долгих уловок и проклятий я обнаружил, что вызывает это, но я не знаю, как его решить.

См. Первую строку JavaScript (пример кода второго). Как вы можете видеть, он объявляет глобальную переменную date. Все делает отлично, но когда я нажимаю на что-то, он будет ссылаться на date, но так как date был обновлен на последней итерации цикла, он всегда будет использовать этот идентификатор.

So. Как я могу убедиться, что date сохраняет личный цикл за итерацию и уверен, что он использует правильное значение в событии?

Примечание

for k, v in dates не работает, либо, так как это делает k глобальным, а также. Поэтому просто использование dates[k].id не будет работать.

ответ

2

Он не объявляет глобальным, что-то общее для этого кода. Если бы это было в пределах функции, это не было бы глобальным.

Проблема не имеет ничего общего с глобальными. Это из-за того, как работают замыкания.Замыкания имеют постоянную ссылку на переменные, которые они закрывают, а не копия их значения с момента создания закрытия. Таким образом, все функции, которые вы создаете для своих обработчиков onTap, используют один и тот же объект, один date.

Чтобы предотвратить это, дайте им что-то свое, чтобы закрыть, что не изменится. Если dates является массивом, используйте forEach.

(Примечание для тех, кто знаком с CoffeeScript, но не Happening:. ! перед -> не обычным ! оператора расширяет CoffeeScript Явления такое, что функция объявлена ​​с помощью !-> вместо ->, неявного возвращаемого значения CoffeeScript как правило, имеет не генерируется )

Так. [С благодаря Erik Dolor для указывая, что из.]:

dates.forEach (date) !-> 
    Dom.section !-> 
     Dom.div !-> 
      Dom.text if date.attending then 'Y' else 'N' 
      Dom.onTap !-> 
       Dom.text date.id 

... который становится это JavaScript:

dates.forEach(function(date) { 
    Dom.section(function() { 
    Dom.div(function() { 
     Dom.text(date.attending ? 'Y' : 'N'); 
     Dom.onTap(function() { 
     Dom.text(date.id); 
     }); 
    }); 
    }); 
}); 

Теперь замыкание создается для каждой итерации forEach обратного вызова закрывает над аргументомdate для этой обратного вызова итерации, который не меняется.