ForEach函数与事件侦听器

时间:2016-02-05 18:29:39

标签: javascript foreach

我想在我的代码中重复一点。在我的一些代码中,有很多元素,我觉得我做得太多了。是时候我学会了如何减少代码并遵循DRY技术。

下面的代码是我当前如何将eventListeners附加到我的元素。

var at1, at2 ,at3 ,at4 ,at5 ,at6 , at7, at8,

at1 = UI.byId("at1");
at1.addEventListener("click", UI.at1Func, false);

at2 = UI.byId("at2");
at2.addEventListener("click", UI.at2Func, false);

at3 = UI.byId("at3");
at3.addEventListener("click", UI.at3Func, false);

at4 = UI.byId("at4");
at4.addEventListener("click", UI.at4Func, false);

at5 = UI.byId("at5");
at5.addEventListener("click", UI.at5Func, false);

at6 = UI.byId("at6");
at6.addEventListener("click", UI.at6Func, false);

at7 = UI.byId("at7");
at7.addEventListener("click", UI.at7Func, false);

at8 = UI.byId("at8");
at8.addEventListener("click", UI.at8Func, false);

我一直在尝试使用forEach循环。但我有这个功能的问题。对于初学者来说,似乎该功能正在被抢占式触发。而且因为我希望我的主要负载反映任何变化,它会产生无限循环和崩溃。我正在使用VS2015,我尝试使用没有任何库的普通JS编写...请,没有jquery。

以下是我对forEach循环的尝试:请参见底部的编辑。

var ats = ['at1', 'at2', 'at3', 'at4', 'at5', 'at6', 'at7', 'at8'];
        ats.forEach(function (key) {
            var ele = UI.byId(key);
            ele.addEventListener("click", UI.atFunc(key), false);
        });

该功能在我的“UI.myLoad”代码块中。这是UI.atFunc(key)...

atFunc: function (key) {
    var value = localStorage.getItem(key);
        localStorage.setItem(key, value++);
        console.log(key);
        //UI.myLoad(); //commented out to prevent crashing for now.
    },

预期的行为是,当单击任何键时,应将1整数的值添加到本地存储中的透视项,并且UI.myLoad只会加载应用程序上的主要主题,值和超时。但是因为我的forLoop在那个代码块中,它导致崩溃。我把它移到UI.myLoad上的范围之外,但它根本不起作用。代码有问题吗?或者我是以错误的方式解决这个问题而应该尝试仅使用for循环?我已经看到forEach正常工作的例子但我不能自己做正确的事。

[编辑:下面的代码是使用已接受答案的解决方案,但发现了另一个问题。现在已确定完整的解决方案。]

(function () {
var UI;
UI = {
byId: function (id) {
        return document.getElementById(id);
},
loadBtns: function () {
    var ats = ['at1', 'at2', 'at3', 'at4', 'at5', 'at6', 'at7', 'at8'];
    ats.forEach(function (key) {
        var ele = UI.byId(key);
        ele.addEventListener("click", UI.atFunc(key), false);
    });
},
myLoad: function () {
    //load and refresh elements
    /*
    var at1 = localStorage.getItem("at1");
        if (!at1) {
            spn1.innerText = 0;               
        }
        if (at1) {
            spn1.innerText = at1;
        }
    ....
    */
},
atFunc: function (key) {
        return function() {
            var value = localStorage.getItem(key);
            localStorage.setItem(key, +value + +1);
            UI.myLoad();
            };
    }
}
window.onload = function () {
    UI.myLoad();
    UI.loadBtns();
}
}())

2 个答案:

答案 0 :(得分:1)

您的问题源于atFunc。它被抢先触发的原因是"是因为你立即调用了这个函数。

ele.addEventListener("click", UI.atFunc(key), false);

这样做是运行函数UI.atFunc然后返回undefined的值。这基本上将您的上述行转换为:

UI.atFunc(key);
ele.addEventListener("click", undefined, false);

相反,您希望返回一个捕获正确密钥的函数。由于函数与JS中的任何其他值一样,您可以返回如下:

atFunc: function(key) {
  return function() {
    var value = localStorage.getItem(key);
    ...
  };
}

这样您就可以返回一个新的函数值而不是undefined,并且该函数绑定到click事件。

答案 1 :(得分:0)

问题在于addEventListener中添加功能的方式。

在第一个代码中,您正确引用了函数

at1.addEventListener("click", UI.at1Func, false);

但在第二个代码中,您添加了括号,并且括号立即调用该函数并返回结果,即undefined

有很多方法可以解决这个问题,但在您的情况下最简单的方法可能是使用闭包修改atFunc函数并返回函数

atFunc: function (key) {
    return function() {
        localStorage[key]++;
    }
},