Разве JavaScript не поддерживает замыкания с локальными переменными? [duplicate]

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

Решение (написано в Swift 4, но общий ответ)

  1. Предполагая, что на любой вопрос может быть не более 8 ответов, создайте 8 кнопок в пользовательской ячейке прототипа , Добавляйте ограничения так, как вам нравится, чтобы они выглядели красиво!
  2. Не забудьте дать вашей ячейке уникальный идентификатор («CustomCell» в моем случае).
  3. Перейдите в «Файл»> «Новый файл»> «Класс касания какао»> выберите подкласс «TableViewCell» & amp; дать ему подходящее имя (в моем случае CustomCellTableViewCell.swift). Он будет содержать все ваши розетки компонентов пользовательского интерфейса.
  4. Выберите ячейку прототипа в вашей раскадровке. Перейдите к третьему значку слева и выберите «CustomCellTableViewCell» в качестве класса.
  5. Control + Перетаскивайте выходы своих кнопок и полей, с которыми вы собираетесь работать, из раскадровки в недавно созданный CustomCellTableViewCell.swift. Теперь файл должен выглядеть примерно так:
class CustomCellTableViewCell: UITableViewCell {
    @IBOutlet weak var question: UILabel!
    @IBOutlet weak var answerOne: UIButton!
    @IBOutlet weak var answerTwo: UIButton!
    ...
    ...
    @IBOutlet weak var answerEight: UIButton!

}
  1. Следующие несколько шагов будут выполнены в функции TableviewDataSource func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell. Не забудьте привести TableviewCell как CustomCell:
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell") as! CustomCellTableViewCell
  1. Поместить все кнопки ответа в массив
var answerButtons = [cell.answerButtonOne, cell.answerButtonTwo..., cell.answerButtonEight]
  1. Теперь вы можете установите текст кнопки ответа в цикле следующим образом:
for i in 0..<answerButtons.count {
  if i < data[indexPath.row].answers.count { // if the answer exists, add it to the button
    cell.answerButton[i].isHidden = false // show button if answer exists 
    cell.answerButton[i].setTitle(data[indexPath.row], for: .normal)
  } else {
    cell.answerButton[i].isHidden = true // hide that button
  }
}
57
задан Anurag 20 May 2010 в 21:05
поделиться

6 ответов

Ответ фиксированного Jon путем добавления дополнительной анонимной функции:

function create() {
  for (var i = 0; i < 5; i++) {
    closures[i] = (function(tmp) {
        return function() {
          alert("i = " + tmp);
        };
    })(i);
  }
}

объяснение состоит в том, что объемами JavaScript является функциональный уровень, не блочный уровень, и создание закрытия просто означает, что объем включения добавляется к лексической среде вложенной функции.

После того, как цикл завершается, переменная функционального уровня i имеет значение 5, и это - то, что 'видит' внутренняя функция.

<час>

Как примечание стороны: необходимо остерегаться ненужного создания функционального объекта, особенно в циклах; это неэффективно, и если Объекты DOM включены, легко создать циклические ссылки и поэтому представить утечки памяти в Internet Explorer.

60
ответ дан Christoph 7 November 2019 в 06:08
поделиться

Я думаю, что это могло бы быть тем, что Вы хотите:

var closures = [];

function createClosure(i) {
    closures[i] = function() {
        alert("i = " + i);
    };
}

function create() {
    for (var i = 0; i < 5; i++) {
        createClosure(i);
    }
}
9
ответ дан Outlaw Programmer 7 November 2019 в 06:08
поделиться

Решение состоит в том, чтобы иметь самовыполняющуюся лямбду, обертывающую Ваше нажатие массива. Вы также передаете i как аргумент той лямбде. Значение я в самовыполняющейся лямбде буду тень значение оригинала я, и все будет работать, как предназначено:

function create() {
    for (var i = 0; i < 5; i++) (function(i) {
        closures[i] = function() {
            alert("i = " + i);
        };
    })(i);
}

Другое решение состояло бы в том, чтобы создать еще одно закрытие, которое получает правильное значение меня и присваивает его другой переменной, которая "поймать" в заключительной лямбде:

function create() {
    for (var i = 0; i < 5; i++) (function() {
        var x = i;

        closures.push(function() {
            alert("i = " + x);
        });
    })();
}
9
ответ дан Ionuț G. Stan 7 November 2019 в 06:08
поделиться

Да закрывают, работают здесь. Каждый раз, когда Вы циклично выполняете функцию, Вы создаете, захватывает i. Каждая функция, которую Вы создаете, совместно использует тот же i. Проблема, которую Вы видите, состоит в том, что, так как они все совместно используют тот же i, они также совместно используют окончательное значение i, так как это - та же полученная переменная.

Редактирование: Эта статья г-на Skeet объясняет закрытия в некоторой глубине и решает эту проблему в особенности способом, которая намного более информативна тогда, я имею здесь. Однако быть осторожным как способ, которым JavaScript и закрытия дескриптора C# имеют некоторые тонкие различия. Пропуск к разделу, названному "Сравнение стратегий получения: сложность по сравнению с питанием" для его объяснения по этой проблеме.

6
ответ дан Andrew Hare 7 November 2019 в 06:08
поделиться

John Resig Изучение Усовершенствованного JavaScript объясняет это и т.д. Это - интерактивная презентация, которая объясняет много о JavaScript, и примерами является забава читать и выполниться.

Это имеет главу о закрытиях, и этот пример взгляды много как Ваш.

Вот поврежденный пример:

var count = 0; 
for ( var i = 0; i < 4; i++ ) { 
  setTimeout(function(){ 
    assert( i == count++, "Check the value of i." ); 
  }, i * 200); 
}

И фиксация:

var count = 0; 
for ( var i = 0; i < 4; i++ ) (function(i){ 
  setTimeout(function(){ 
    assert( i == count++, "Check the value of i." ); 
  }, i * 200); 
})(i);
3
ответ дан Sébastien RoccaSerra 7 November 2019 в 06:08
поделиться

Вот то, что необходимо сделать для достижения результата:

<script>
var closures = [];
function create() {  
    for (var i = 0; i < 5; i++) {   
        closures[i] = function(number) {      
        alert("i = " + number);   
        };  
    }
}
function run() {  
    for (var i = 0; i < 5; i++) {   
        closures[i](i); 
    }
}
create();
run();
</script>
-1
ответ дан Billy 7 November 2019 в 06:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: