如何压缩此重复代码并使其动态化?

时间:2015-06-11 09:50:27

标签: javascript jquery refactoring code-duplication

我有一些重复的代码将下拉过滤器添加到我的DataTable(使用jQuery DataTables插件),看起来像这样:

// filter based on company type
$.fn.dataTable.ext.search.push(
    function( settings, data, dataIndex ) {
        selectedType = $('#companyType').val();
        if(selectedType.toLowerCase() === "all"){
            return true;    
        }
        if(selectedType.toLowerCase() === data[2].toLowerCase()){
            return true;                    
        }
        return false;
    }
);

// filter based on status type
$.fn.dataTable.ext.search.push(
    function( settings, data, dataIndex ) {
        selectedType = $('#status').val();
        if(selectedType.toLowerCase() === "all"){
            return true;    
        }
        if(selectedType.toLowerCase() === data[3].toLowerCase()){
            return true;                    
        }
        return false;
    }
);

// filter based on account type
$.fn.dataTable.ext.search.push(
    function( settings, data, dataIndex ) {
        selectedType = $('#accountType').val();
        if(selectedType.toLowerCase() === "all"){
            return true;    
        }
        if(selectedType.toLowerCase() === data[9].toLowerCase()){
            return true;                    
        }
        return false;
    }
);

如您所见,这些函数之间的唯一区别是elementID(过滤器下拉列表)和列索引。我想使用循环或函数来分解重复的代码并使其可重用。

我尝试在javascript中使用键值对象,然后循环为每个对象添加一个过滤器:

<!--- Create object that stores key-value pairs for all dropdown filters; key is column index, value is filter element ID --->
var dropDownFilters = { 2: "companyType", 3: "status", 9: "accountType" }
<!--- Loop through dropdown filters and set filter for each --->
for(var key in dropDownFilters){
    $.fn.dataTable.ext.search.push(
        function( settings, data, dataIndex ) {
            selectedType = $('#' + dropDownFilters[key]).val();
            if(selectedType.toLowerCase() === "all"){
                return true;    
            }
            if(selectedType.toLowerCase() === data[key].toLowerCase()){
                return true;                    
            }
            return false;
        }   
    );      
}

这不能正常工作,因为它只创建具有最后值(9和accounttype)的过滤器功能,因此第三个过滤器可以工作,但其他过滤器没有。

我可以通过加载服务器端的coldfusion代码来完成我想要完成的任务:

<cfset dropDownFilters = [  { colIndex=2, elementID = "companyType" }, 
                            { colIndex=3, elementID = "status"},
                            { colIndex=9, elementID = "accountType"} ] />
<cfloop from="1" to="#ArrayLen(dropDownFilters)#" index="i">
    $.fn.dataTable.ext.search.push(
        function( settings, data, dataIndex ) {
            selectedType = $('#<cfoutput>#dropDownFilters[i].elementID#</cfoutput>').val();
            if(selectedType.toLowerCase() === "all"){
                return true;    
            }
            if(selectedType.toLowerCase() === data[<cfoutput>#dropDownFilters[i].colIndex#</cfoutput>].toLowerCase()){
                return true;                    
            }
            return false;
        }   
    );
</cfloop>

然而,这感觉很笨拙。我更喜欢通过纯粹的javascript实现这一点,没有理由让ColdFusion参与其中。

如何使用循环或函数重构这个重复的代码(哪个更好)?

1 个答案:

答案 0 :(得分:1)

您可以创建function以重用某些代码。代码重复是编程中antipattern之一。

function prepare(selector, index)
{
    $.fn.dataTable.ext.search.push(
        function( settings, data, dataIndex ) {
            selectedType = $(selector).val();
            if(selectedType.toLowerCase() === "all"){
                return true;    
            }
            if(selectedType.toLowerCase() === data[index].toLowerCase()){
                return true;                    
            }
            return false;
        }
    );
}

然后你的代码看起来像:

prepare('#companyType', 2);
prepare('#status', 3);
prepare('#accountType', 9);