经典臭名昭着的循环困境的变异

时间:2011-07-19 19:45:27

标签: javascript closures

几乎所有人都遇到了这个具体问题:

function addLinks () {
    for (var i=0, link; i<5; i++) {
        link = document.createElement("a");
        link.innerHTML = "Link " + i;
        link.onclick = function () {
            alert(i);
        };
        document.body.appendChild(link);
    }
}
window.onload = addLinks;

缓存循环后i的值。闭包可用于创建“实时”引用:

function addLinks () {
    for (var i=0, link; i<5; i++) {
        link = document.createElement("a");
        link.innerHTML = "Link " + i;
        link.onclick = function (num) {
            return function () {
                alert(num);
            };
        }(i);
        document.body.appendChild(link);
    }
}
window.onload = addLinks;

我们也可以使用自动执行anon fns来创建闭包等。

我的情况

我面临的问题是相同的,但背景略有不同。这是一个failing example

点击“添加更多lis”几次,然后点击“点击我”,这会提醒-1。缓存maxIndex的值。相关代码:

  var attached = false;

function actions() {
    var elements = $('body').find('li');
    var maxIndex = elements.length -1;


        var cycle = {
            next: function() {
                alert( maxIndex );
            }
        };

        if ( !attached ) {
            $('#next').click(function(e) {
                cycle.next();
            });
            attached = true;
        }

};

actions();

$('#add').click(function(e) {
    e.preventDefault();
    $('<li/>').text('god').appendTo('body');
    actions();
});

我尝试过应用封口无济于事。 (见http://jsfiddle.net/Bfcus/23/并下至/ 1 /)。

我不想使用with语句或let语句/表达式来解决这个问题。我知道另一种可解决的方法是将maxIndex更改为命名对象的属性。这是一个有效的example

我想知道的是 - 是否有一种方法可以使elements变量定义保留在action函数内部,并在maxIndex函数中定义{{1}}变量相同的范围?基本上,http://fiddle.jshell.net/r7Ekj/2/show/可以调整为几乎以同样的方式工作,而不依赖于/ let / object属性吗?

1 个答案:

答案 0 :(得分:1)

很奇怪,有时创造一个彻底的问题实际上可以帮助你解决它,我发誓我事先没有解决它...

我刚刚在maxIndex范围之外创建了actions变量并实际将其分配到内部..这使得它工作,因为它没有在相同的函数范围中定义,因此绑定的行为不同

http://fiddle.jshell.net/r7Ekj/9/

(多么令人尴尬?)