范围问题

时间:2015-09-16 12:12:17

标签: javascript for-loop

我正在尝试为我循环的每个子元素分配一个处理程序。我的问题是:target = child.items[i].id;将拥有我循环的最后一个元素的id。所以这一部分:

    fn: function() {
        isoNS.injectKey(target);
    }

将始终具有最后一个孩子的id(目标)。我怎样才能做到这一点? 我尝试将this置于前面,如下所示:isoNS.injectKey(this.target);

var arr=[];

for(var i = 0; i < obj.items.length; ++i) {
    target = child.items[i].id;
    arr.push({
        key: sHolder.charAt(i),
        fn: function() {
            isoNS.injectKey(target);
        },
    });
}

所以我的主要问题是,每次使用最新元素时,每个不同的值target = child.items[i].id;都会被覆盖。我希望我能让自己明白。

如果你想知道obj和孩子是什么......我把它们排除在外以使代码更短更容易理解。只知道他们确实有值,并且永远不会为空

3 个答案:

答案 0 :(得分:3)

你可以这样做

var arr = Array.prototype.map.call(obj.items, function(obj, i) {
    return {
        key: sHolder.charAt(i),
        fn: function() {
            isoNS.injectKey(child.items[i].id);
        }
    };
});

Array map函数提供了闭包,以及构建arr

的更好方法

我使用Array.prototype.map.call因为没有迹象表明obj.items是否为TRUE数组...如果是,那么它就更简单了

var arr = obj.items.map(function(obj, i) {
    return {
        key: sHolder.charAt(i),
        fn: function() {
            isoNS.injectKey(child.items[i].id);
        }
    };
});

答案 1 :(得分:2)

问题是你的函数是一个闭包,它捕获了对目标变量的引用,在调用回调之前,你的循环会改变它。解决此问题的一种简单方法是将函数包装在另一个捕获目标变量值的闭包中。

你可以这样做:

(function(capturedValue){
    return function () {
        // do something with the capturedValue
    };
}(byRefObject));

第一个函数是立即调用函数表达式(IIFE)的一部分。它用于捕获byRefObject的值。您可以阅读有关IIFE here的更多信息。

您的代码可能如下所示:

var arr=[];

for(var i = 0; i < obj.items.length; ++i) {
    target = child.items[i].id;
    arr.push({
        key: sHolder.charAt(i),
        fn: (function(target) {
                return function() {
                    isoNS.injectKey(target);
                };
             })(target)
        },
    });
}

答案 2 :(得分:1)

这与闭包有关:

var arr=[];

function getFunc(t){ 
          return function() {
            isoNS.injectKey(t);
        }};

for(var i = 0; i < obj.items.length; ++i) {
    target = child.items[i].id;
    arr.push({
        key: sHolder.charAt(i),
        fn: getFunc(target),
    });
}