Javascript 最佳实践:循环中的函数

Javascript 最佳实践:循环中的函数,javascript,function,loops,Javascript,Function,Loops,我得到了下面的代码,它工作得非常好。它的作用是:在表格中,当您将鼠标悬停在任何表格单元格上时,它会高亮显示相应的表格标题单元格和表格第一列单元格 // Row & Column Highlight (function() { var gridCellRow = null, gridCellCol = null, tableElement = document.getElementsByClassName('inner_table');

我得到了下面的代码,它工作得非常好。它的作用是:在表格中,当您将鼠标悬停在任何表格单元格上时,它会高亮显示相应的表格标题单元格和表格第一列单元格

  // Row & Column Highlight
 (function() {

     var gridCellRow = null,
         gridCellCol = null,
         tableElement = document.getElementsByClassName('inner_table');
     for (var i = 0, len_i = tableElement.length; i < len_i; i++) {
         if (tableElement[i].getElementsByClassName('row_label_cell').length > 0) {
             var gridCell = tableElement[i].getElementsByClassName('input_cell');
             for (var j = 0, len_j = gridCell.length; j < len_j; j++) {
                 function gridCellParents(currentCell) {
                     return gridCellRow = currentCell.parentNode.firstElementChild,
                         gridCellCol = currentCell.parentNode.parentNode.rows[0].cells[currentCell.cellIndex];
                 }
                 gridCell[j].addEventListener('mouseover', (function() {
                     gridCellParents(this);
                     gridCellRow.classList.add('highlight');
                     gridCellCol.classList.add('highlight');
                 }));
                 gridCell[j].addEventListener('mouseout', (function() {
                     gridCellRow.classList.remove('highlight');
                     gridCellCol.classList.remove('highlight');
                 }));
             }
         }
     }

 }());
“不要在循环中生成函数”不是最佳实践

那么,我如何根据最佳实践正确构建整个功能呢

函数减速不应在循环内,因为它不会 一次又一次地重新创建同一个函数的感觉 “连续流动”(与其他相同功能的情况不同 可以在更复杂的代码中再次创建)。主要原因是 因为,它强烈反对javascript 在循环中编写函数声明的原则

一个良好的起点,代码更加有序:

     // Row & Column Highlight
(function() {
    var gridCellRow,
        gridCellCol,
        gridCell,
        tableElement = document.getElementsByClassName('inner_table');   

    function gridCellParents(currentCell) {
        gridCellRow = currentCell.parentNode.firstElementChild,
        gridCellCol = currentCell.parentNode.parentNode.rows[0].cells[currentCell.cellIndex];
    }

    function onMouseEnter() {
        gridCellParents(this);
        gridCellRow.classList.add('highlight');
        gridCellCol.classList.add('highlight');
    }

    function onMuoseLeave() {
        gridCellRow.classList.remove('highlight');
        gridCellCol.classList.remove('highlight');
    }


    for (var i = 0, len_i = tableElement.length; i < len_i; i++) {
        if (tableElement[i].getElementsByClassName('row_label_cell').length > 0) {
            gridCell = tableElement[i].getElementsByClassName('input_cell');                    
            for (var j = 0, len_j = gridCell.length; j < len_j; j++) {
                gridCell[j].addEventListener('mouseenter', onMouseEnter);
                gridCell[j].addEventListener('mouseleave', onMuoseLeave);
            }
        }
}}());
函数减速不应在循环内,因为它不会 一次又一次地重新创建同一个函数的感觉 “连续流动”(与其他相同功能的情况不同 可以在更复杂的代码中再次创建)。主要原因是 因为,它强烈反对javascript 在循环中编写函数声明的原则

一个良好的起点,代码更加有序:

     // Row & Column Highlight
(function() {
    var gridCellRow,
        gridCellCol,
        gridCell,
        tableElement = document.getElementsByClassName('inner_table');   

    function gridCellParents(currentCell) {
        gridCellRow = currentCell.parentNode.firstElementChild,
        gridCellCol = currentCell.parentNode.parentNode.rows[0].cells[currentCell.cellIndex];
    }

    function onMouseEnter() {
        gridCellParents(this);
        gridCellRow.classList.add('highlight');
        gridCellCol.classList.add('highlight');
    }

    function onMuoseLeave() {
        gridCellRow.classList.remove('highlight');
        gridCellCol.classList.remove('highlight');
    }


    for (var i = 0, len_i = tableElement.length; i < len_i; i++) {
        if (tableElement[i].getElementsByClassName('row_label_cell').length > 0) {
            gridCell = tableElement[i].getElementsByClassName('input_cell');                    
            for (var j = 0, len_j = gridCell.length; j < len_j; j++) {
                gridCell[j].addEventListener('mouseenter', onMouseEnter);
                gridCell[j].addEventListener('mouseleave', onMuoseLeave);
            }
        }
}}());

除了前面的答案外,我认为还必须说明为什么这是一种不好的做法

在循环内创建函数时的问题是,它们经常使用依赖于循环迭代的值。让我们举个例子

//创建三个函数,用于写入它们的编号
var funcs=[];

对于(var i=0;i除了前面的答案外,我认为还必须说明为什么这是一种不好的做法

在循环中创建函数的问题是,它们经常使用依赖于循环迭代的值

//创建三个函数,用于写入它们的编号
var funcs=[];


对于(var i=0;iso将其从循环中取出,有什么问题?当然不应该在循环中!反复创建完全相同的函数有意义吗?一点常识;)因此,将函数声明移到循环之外。我知道这是没有意义的,这就是为什么我要征求关于如何以正确的方式构建它的建议和一个小例子。那么,将它从循环中移除,有什么问题吗?当然它不应该在循环中!反复创建完全相同的函数有意义吗?有点常见因此,将函数声明移到循环之外。我知道这是没有意义的,这就是为什么我要征求关于如何正确构建此函数的建议和示例。非常感谢。这在我看来是合理的。是否可以以任何方式调用onMouseEnter和onMouseLeave作为匿名函数?@sangriab我已经修改了代码,使其更具逻辑性,因此现在有一个名为
toggleHighlight
的函数。好吗?@vsync:它做得越好,我能学的就越多。请这样做。它会变得更疯狂:)我真的很好奇。如果你有任何进一步的改进建议,请与我分享。我很感激能认识新事物。非常感谢。这在我看来是合理的。是否可以以任何方式调用onMouseEnter和onMouseLeave作为匿名函数?@sangriab我已经修改了代码,使其更具逻辑性,因此现在有一个名为
toggleHighlight
的函数。好吗?@vsync:它做得越好,我能学的就越多。请这样做。它会变得更疯狂:)我真的很好奇。如果你有任何进一步的改进建议,请与我分享。我很感谢能够了解新事物。在循环的每个迭代中评估/创建函数也有点昂贵。只创建一次函数更便宜。这是真的。虽然你必须循环很多次才能看到区别。大多数时候我不会太担心这个。首先是可读性。在循环的每个迭代中评估/创建函数也有点昂贵。只创建一次函数更便宜。这是真的。虽然你必须循环很多次才能看到区别。大多数时候我不会太担心这个。可读性第一。
     // Row & Column Highlight
(function() {
    var gridCellRow,
        gridCellCol,
        gridCell,
        tableElement = document.getElementsByClassName('inner_table');   

    function gridCellParents(currentCell) {
        gridCellRow = currentCell.parentNode.firstElementChild,
        gridCellCol = currentCell.parentNode.parentNode.rows[0].cells[currentCell.cellIndex];
    }

    function onMouseEnter() {
        gridCellParents(this);
        gridCellRow.classList.add('highlight');
        gridCellCol.classList.add('highlight');
    }

    function onMuoseLeave() {
        gridCellRow.classList.remove('highlight');
        gridCellCol.classList.remove('highlight');
    }


    for (var i = 0, len_i = tableElement.length; i < len_i; i++) {
        if (tableElement[i].getElementsByClassName('row_label_cell').length > 0) {
            gridCell = tableElement[i].getElementsByClassName('input_cell');                    
            for (var j = 0, len_j = gridCell.length; j < len_j; j++) {
                gridCell[j].addEventListener('mouseenter', onMouseEnter);
                gridCell[j].addEventListener('mouseleave', onMuoseLeave);
            }
        }
}}());
 // Row & Column Highlight
(function() {
    var gridCell,
        tableElement = document.querySelectorAll('.inner_table');   

    function getCellParents(cell){
        return {
            row : cell.parentNode.firstElementChild,                       // row
            col : cell.parentNode.parentNode.rows[0].cells[cell.cellIndex] // col
       }; 
    }

    function updateGridCellParents(cell, state) {
        state = state ? 'add' : 'remove';

        var parents = getCellParents(cell);

        parents.row.classList[state]('highlight');
        parents.col.classList[state]('highlight');
    }

    funciton checkTarget(target){
        // make sure the element is what we expected it to be
        return target.className.indexOf('input_cell') != 0;
    }

    function onMouseEvents(e){
        checkTarget(e.target) && updateGridCellParents(e.target, e.type == "mouseover");
    }

    document.body.addEventListener('mouseover', onMouseEvents);
    document.body.addEventListener('mouseout', onMouseEvents);
})();