简化复杂的if语句

时间:2012-08-05 16:57:04

标签: javascript backbone.js

以下代码取自Backbone.js Events#off()

如何简化IF部分以便于理解?

for (i = list.length - 2; i >= 0; i -= 2) {
    if (!(callback && list[i] !== callback || context && list[i + 1] !== context)) {
        list.splice(i, 2);
    }
}

5 个答案:

答案 0 :(得分:3)

var noCallback = callback && list[i] !== callback;
var noContext = context && list[i + 1] !== context;
if(! noCallback && ! noContext){...}

或者删除评论中建议的否定:

var callbackCheck = !callback || list[i] === callback;
var contextCheck = !context || list[i + 1] === context;
if(callbackCheck && contextCheck ){...}

答案 1 :(得分:2)

一些布尔数学:

!(callback && list[i] !== callback || context && list[i + 1] !== context)
!(!(!callback || list[i] === callback) || !(!context || list[i + 1] === context))
(!callback || list[i] === callback) && (!context || list[i + 1] === context)

我认为disjunctive normal form比被否定的conjunctive normal form更容易理解。

为了使单个部分更容易理解,请使用说话变量名称(我不知道其范围,你可能会找到更好的东西):

var rightCallback = !callback || list[i] === callback;
var rightContext = !context || list[i + 1] === context;
if (rightCallback && rightContext) {…}

答案 2 :(得分:0)

我建议将语句封装到带有描述性名称的函数中(我不明白你想做什么),然后调用

if (true == meaningfulConditionName(list, callback))
{
    list.splice(i, 2);
}

答案 3 :(得分:0)

不能简化为:

for (i = list.length - 2; i >= 0; i -= 2) callback && list[i] !== callback || context && list[i + 1] !== context || list.splice(i, 2)

答案 4 :(得分:-1)

这是我的版本,通过了所有Backbone.js测试,并且比原来的

  if(
      // callback defined, context is null
      // remove callback for all context
      ( callback && list[i] === callback
         && !context)

      // callback defined and context is defined
      // ie remove specified callback for specified context
      || ( callback && list[i] === callback
           && context && list[i+1] === context)

      // callback NOT defined and context is defined
      // ie removed all callback for specific context
      || ( !callback && list[i] !== callback
           && context && list[i+1] === context )

      // callback NOT defined and context NOT defined
      // i.e. removed everything, this is unreachable code
      // as it is caught by 
      // https://github.com/documentcloud/backbone/blob/master/backbone.js#L112
      // and https://github.com/documentcloud/backbone/blob/master/backbone.js#L103
      || ( !callback && !context )

      ) {

            // remove callback and context
            list.splice( i, 2 );
  }