Переменная в событии - PullRequest
       45

Переменная в событии

2 голосов
/ 23 декабря 2009

Я получил этот код:

<script>window.onload = function () {
    var container, i;

    for (i = 0; i < 10; i ++) {
        container = document.createElement ("div");
            container.innerHTML = i;

            container.style.border = "1px solid black";
            container.style.padding = "10px";

            container.onclick = function () {
                alert (i);
            }

        document.body.appendChild (container);
    }
}</script>

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

Спасибо

Ответы [ 7 ]

3 голосов
/ 23 декабря 2009

Это классическая проблема с анонимными функциями.

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

Вы хотите создать новую область видимости для каждой переменной: что-то вроде:

function createAlertFunction(i) {
    return function() {
        alert(i);
    }
}

//...

container.onclick = createAlertFunction(i);
2 голосов
/ 23 декабря 2009

Вам нужно создать для каждой итерации свою функцию. Попробуйте вместо этого:

container.onclick = (function(i) {
    return function() {
        alert(i);
    };
})(i);

Здесь внешняя функция (function(i) { … }) используется для возврата новой функции со значением i. Когда эта функция вызывается ((function(i) { … })(i)), i передается этой функции и встраивается в возвращаемую функцию.

1 голос
/ 23 декабря 2009

Аналогично Gumbo и Anon , хотя лично мне это немного легче читать (только мое мнение).

window.onload = function () {
        var container, i;

        for (i = 0; i < 10; i ++) {
            (function() {
                container = document.createElement ("div");
                container.innerHTML = i;

                container.style.border = "1px solid black";
                container.style.padding = "10px";

                container.onclick = function () {
                                        alert (i);
                                    };

                document.body.appendChild (container);
            })();
       }
}
1 голос
/ 23 декабря 2009

Оно не отображает неправильное значение, оно отображает значение i, когда вызывается внутренняя анонимная функция. Я думаю, вы ожидаете, что он будет отображать значение i, когда функция была связана с событиями onclick соответствующих элементов div.

0 голосов
/ 23 декабря 2009

Вместо того, чтобы создавать большое количество практически идентичных функций с помощью замыканий, почему бы не попробовать что-то вроде этого:

function containerOnClick () {
    alert(this.index);
}

window.onload = function() {
    var container, i;
    for (i = 0; i < 10; i++) {
        // -- snip --
        container.index = i;
        container.onclick = containerOnClick;
    }
};

В зависимости от размера обработчика onclick, а также от количества контейнеров, которое у вас будет в общей сложности, это может значительно уменьшить объем используемой памяти.

0 голосов
/ 23 декабря 2009

Вы можете использовать with

var container, i;
for (i = 0; i < 10; i ++) {
    with ({ locali: i }) {
        container = document.createElement ("div");
        container.innerHTML = i;
        container.style.border = "1px solid black";
        container.style.padding = "10px";
        container.onclick = function () {
            alert(locali);
        }
    }
    document.body.appendChild(container);
}

По сравнению с решением для анонимных функций, упомянутым ранее, оно немного менее производительно (что имеет значение, если вы называете его десятки из тысяч раз), и работает намного лучше с отладчиком Visual Studio (и, возможно, другими).

0 голосов
/ 23 декабря 2009

Здесь вы пытаетесь создать нечто, называемое «закрытие». Он закрывает последний известный контекст значением переменной «i». Поэтому, чтобы получить правильное значение внутри замыкания, вы должны создать новый контекст, передав значение переменной в новую локальную область видимости внутренней функции. Подробнее о закрытиях: http://www.jibbering.com/faq/faq%5Fnotes/closures.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...