以函数式方式重构 JS 代码——闭包

Refactoring JS code in a functional way - closures

我有以下重复代码,用于在满足特定条件时突出显示 html/css 代码的一部分。即,当我对select三个元素进行布局时。因为,selection 的顺序无关紧要,我必须重复代码三次,为每个元素创建侦听器。

因此,我想重构为更实用的风格,如闭包。

for (var m=0; m < selectedDessert.length; m++){
    selectedDessert[m].addEventListener("click", function(){
    if (buyImages.length + buyImagesDrink.length + buyImagesDessert.length === 3){
        footerStyle[0].classList.add("order");
        footerStyleSpan.innerHTML = "string";
        
    }});
    selected[m].addEventListener("click", function(){
    if (buyImages.length + buyImagesDrink.length + buyImagesDessert.length === 3){
        footerStyle[0].classList.add("order");
        footerStyleSpan.innerHTML = "string";
    }});
    selectedDrink[m].addEventListener("click", function(){
    if (buyImages.length + buyImagesDrink.length + buyImagesDessert.length === 3){
        footerStyle[0].classList.add("order");
        footerStyleSpan.innerHTML = "string";
        
    }});
};

我想在这些行中重构他:

let combinedVar = buyImages.length + buyImagesDrink.length + buyImagesDessert.length;
var funcOrder = function(selectVar) {
    let selectedVar = selectVar;
    selectVar[i].addEventListener("click", function(){
    if (combinedVar === 3){
        footerStyle[0].classList.add("order");
        footerStyleSpan.innerHTML = "Fechar pedido";
    }
    });
};

var pSelectedDessert = funcOrder(selectedDessert);
var pSelectedDrink = funcOrder(selectedDrink);
var pSelected = funcOrder(selected);

for (var i = 0; i < selected.length; i++) {
    pSelectedDessert();
    pSelectedDrink();
    pSelected();
}
Error:
highlight-all.js:29 Uncaught TypeError: Cannot read property 'addEventListener' of undefined
    at funcOrder (highlight-all.js:29)
    at highlight-all.js:37

Error-line:
selectVar[i].addEventListener("click", function(){

问题是:我如何将变量传递给此函数,因为它尚未定义(执行不同)。


演示: https://jsfiddle.net/BuddhiLW/q3mwe9ky/13/

无需使用闭包或尝试函数式方法(使用 dom 和响应事件无论如何都需要命令式风格)。

您可以做的第一个简化是使用命名函数,而不是重复三次相同的函数表达式 - 它是完全相同的代码,甚至不依赖于具有不同值的闭包变量。

function handleClick() {
    if (buyImages.length + buyImagesDrink.length + buyImagesDessert.length === 3) {
        footerStyle[0].classList.add("order");
        footerStyleSpan.innerHTML = "string";
    }
}
for (var m=0; m < selectedDessert.length; m++) {
    selectedDessert[m].addEventListener("click", handleClick);
    selected[m].addEventListener("click", handleClick);
    selectedDrink[m].addEventListener("click", handleClick);
}