簡體   English   中英

如何簡化用underscore.js編寫的這個過濾器?

[英]How to simplify this filter written in underscore.js?

給定是一個具有一系列條件的對象:

var conditions = {
    even: function (i) { return i % 2 == 0; },

    greatherThan: function (i) { return i > 10; },

    inValidRange: function (i) {
        return i > 20 && i < 100;
    }
};

以及從0到39的范圍內的數組編號: var numbers = _.range(0, 40);

我想按各種條件過濾numbers 我使用underscore.js來做到這一點:

var result = _.filter(numbers, function(current) {

    return _.all(_.values(conditions), function(f) { 
        return f(current);
    });

});
// returns [ 22, 24, 26, 28, 30, 32, 34, 36, 38 ]

它工作正常,但不幸的是,上面的代碼看起來很奇怪,而且非常令人困惑。

如何簡化此代碼以使其更易讀和易懂?

這個輔助函數可能很有用:

_.mixin({
    invokeWith: function() {
        var args = arguments;
        return function(fn) {
             return fn.apply(null, args);
        };
    }
});

如果你的conditions是一個陣列,那也會更好。 您可以使用一組命名函數:

var conditions = [
    function even(i) { return i % 2 == 0; },
    function greaterThan(i) { return i > 10; },
    function inValidRange(i) { return i > settings.validRange.from && i < settings.validRange.to; }
];

或者之前轉換它,以便我們可以省略(並且不需要重復調​​用) values函數:

conditions = _.values(conditions);

現在您可以將代碼縮短到

var result = _.filter(numbers, function(current) {
    return _.all(conditions, _.invokeWith(current));
});

理解發生的事情可能會更復雜,因為大多數人都必須查找invokeWith函數,但是這個概念更容易理解,因為代碼是完全聲明的,包含構建自然表達式的所有動詞current調用所有條件

如果想要刪除外部lambda表達式,它會變得更短但更難理解:

// functional programming FTW :-)
var result = _.filter(numbers, _.compose(_.partial(_.all, conditions), _.invokeWith));

沒有必要重寫該代碼; 把它放在一個命名函數中:

function filterByConditions(values, conditions){
  return _.filter(values, function(current) {

    return _.all(_.values(conditions), function(f) { 
      return f(current);
    });

  });
}

函數中的代碼並不復雜,不應該與熟悉underscore.js的人混淆。 如果您認為有必要,可以在函數體中添加注釋。 無論哪種方式,當您在其他地方使用該函數時,應該清楚該函數從名稱中執行的操作:

var result = filterByConditions(numbers, conditions);

如果你想簡化函數的主體,那么不熟悉underscore.js的開發人員仍然可以讀取它,你可以用簡單的for ... in循環替換_all_values 大多數Javascript開發人員可以在沒有使用underscore.js的情況下推斷_.filter的作用:

function filterByConditions(values, conditions){
  return _.filter(values, function(current){

    for(condition_name in conditions){

      if(!conditions[condition_name](current)){
        // Condition failed
        return false;
      }

    }

    // All conditions passed
    return true;

  });
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM