#javascript #closures
#javascript #замыкания
Вопрос:
Как работает закрытие JavaScript в этом случае и, если быть более конкретным: что делает (i)
в конце?
for(var i = 0; i < 10; i ) {
(function(e) {
setTimeout(function() {
console.log(e);
}, 1000);
})(i);
}
Также я пытаюсь реализовать это в своем коде, и, похоже, у меня что-то не получается
for (var i=0; i < len; i ) {
var formID = document.forms["form-" i];
$(formID).bind("submit", validate);
$(formID).bind("change", function(i){
var divI = '#ind-' i;
$(divI).css("background-color","green");
})(i);
}
Комментарии:
1.Если вы хотите узнать больше о закрытиях, вот несколько ссылок, которые могут помочь: vimeo.com/1967261 jibbering.com/faq/notes/closures
2. Видео действительно отличное, спасибо
Ответ №1:
Это шаблон, используемый для создания локальной области видимости вокруг переменной. Если бы это не использовалось, то каждый вызов console.log(i)
i
регистрировал бы значение в (10) после завершения цикла for.
for(var i = 0; i < 10; i ) {
// create new function
(function(e) {
// log each counter after 1 second.
setTimeout(function() {
console.log(e);
}, 1000);
// execute it with the counter
})(i);
}
Вышесказанное аналогично этому.
function foobar(e) {
setTimeout(function() {
console.log(e);
}, 1000);
}
for (var i = 0; i < 10; i ) {
(
foobar
)(i);
}
Настоящая проблема здесь заключается в создании функций в цикле. не делайте этого 🙂
Ваш код
for (var i=0; i < len; i ) {
var formID = document.forms["form-" i];
$(formID).bind("submit", validate);
// create a full closure around the block of code
(function() {
$(formID).bind("change", function(i){
var divI = '#ind-' i;
$(divI).css("background-color","green");
})//(i); Don't call (i) here because your just trying to execute the
// jQuery element as a function. You can't do this, you need to wrap
// an entire function around it.
})(i);
}
Но это неправильно, вы хотите делегировать эту работу чему-то другому.
function makeGreen(form, i) {
$(form).change(function() {
$("#ind-" i).css("background-color", "green");
});
}
for (var i=0; i < len; i ) {
var formID = document.forms["form-" i];
$(formID).bind("submit", validate);
// call a helper function which binds the change handler to the correct i
makeGreen(formID, i);
}
Если вы хотите немного поумнеть, вы можете избавиться от этих анонимных функций
function makeGreen() {
var divId = $(this).data("div-id");
$(divId).css("background-color", "green");
}
for (var i=0; i < len; i ) {
$(document.forms["form-" i])
.bind("submit", validate)
// store i on the form element
.data("div-id", "#ind-" i)
// use a single event handler that gets the divId out of the form.
.change(makeGreen);
}
Редактировать
( // contain the function we create.
function(parameterA) {
window.alert(parameterA);
}
) // this now points to a function
("alertMessage"); // call it as a function.
Это то же самое, что
( // contain the window.alert function
window.alert
) // it now points to a function
("alertMessage"); // call it as a function
Комментарии:
1. спасибо @ Raynos, я вижу это, но я не совсем понимаю, как это работает и как это реализовать в моем коде (я отредактировал вопрос), есть предложения? 🙂
2. 1 за «Реальная проблема здесь заключается в создании функций в цикле. не делайте этого » (предполагая, что вы говорите о немедленно вызванном ). Возможно, добавить пример именованной функции?
3. Лично я не уверен, что мне не нравятся подобные встроенные лямбды. Я думаю, это вопрос стиля, и, конечно же, на это влияет опыт работы с другими функциональными языками. Я вижу обе стороны аргумента, но я не уверен, какая из них выигрывает 🙂
4. @Pointy @T.J.Crowder Я думаю, что второй пример лучше, вместо привязки этих данных к закрытию вы привязываете их к элементу DOM, который является гораздо «более дешевым» местом для его существования. @T.J.Crowder Также извините, что испортил ваш ответ
5. @Raynos: Я согласен. И, ЛОЛ, не беспокойтесь, отличный ответ.
Ответ №2:
Хотя это и не прямой ответ на вопрос о закрытии, вот мой взгляд на проблему.
Я бы переписал логику, чтобы избежать необходимости закрытия (поскольку это кажется чрезмерно сложным для требований)
Тот факт, что в именовании форм присутствует шаблон, действительно упрощает задачу
$('form[id^="form-"]').submit(validate)
.change(function(){
var divI = '#ind-' this.id.replace('form-','');
$(divI).css("background-color","green");
});
Комментарии:
1. спасибо, но я не понимаю
form[id^="form-"]
, что это делает?2. @IlyaD, это селектор атрибута, который начинается с . Это означает найти все,
forms
чьиid
начинаются с"form-"
.