2012-08-05 4 views
1

Этот следующий код взят из Backbone.js Events#off()Simplify осложнено, если оператор

Как можно упростить, если часть, так что легко понять?

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

Err, они сохраняют в массиве 2 разных типа, вместо того, чтобы создавать новый тип и хранить массив этого типа в одиночку ... вздох. – Esailija

+0

Я видел более сложную логику 'if', чем это на сегодняшний день. Тем не менее, я не получаю вашу группу на тестах. –

ответ

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) {…} 
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){...} 
+0

это работает, однако это не облегчает понимание со всеми отрицаниями. – portoalet

+2

Я даже пошел дальше. 'NOT no X' является нечетным выражением ... – Bergi

+0

@Bergi Хорошо, я отредактировал свой ответ, чтобы принять его во внимание. – kgautron

0

Я предлагаю, чтобы инкапсулировать заявление в функцию с описательным именем (я не понимаю, что вы хотите делать), а затем вызвать

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

Не используйте условия yoda и никогда не проверяйте логическую переменную для equalitiy на 'true' – Bergi

-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); 
    }       
+0

Это кажется мне менее понятным и не соответствует логике исходного кода. В оригинале, если нет «обратного вызова» и нет «контекста», произойдет «сращивание». В твоем, это не будет. –

+0

спасибо за обнаружение, я добавил (! Callback &&! Context) check, и это будет недостижимый код. – portoalet

+0

Ничего себе, полная дизъюнктивная нормальная форма! – Bergi

0

не может быть упрощена больше, чем это:

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