Во-первых, есть три результата ваша функция может имеют: ничего не делать, звоните this.close()
или звоните this.open()
. Поэтому в идеале результирующая функция будет иметь только один оператор if, определяющий, какой результат используется.
Следующим шагом является извлечение всего булева кода в переменные. Например, var leftPastCenter = this.content.getBoundingClientRect().left > viewport/2
.
Наконец, используйте логическую логику, чтобы упростить ее шаг за шагом.
Вот как я это сделал:
Во-первых, извлечь все булевы переменные:
function() {
var duration = +new Date() - start.time,
isPastHalf = Number(duration) < 250 && Math.abs(delta.x) > 20 || Math.abs(delta.x) > viewport/2,
direction = delta.x < 0,
leftPastCenter = this.content.getBoundingClientRect().left > viewport/2,
positiveDelta = this.isEmpty(delta) || delta.x > 0,
isPulled = pulled === true; // I'll assume the test is needed rather than just using pulled.
if (!isScrolling) {
if (isPastHalf) {
if (direction) {
this.close();
} else {
if (leftPastCenter && isPulled) {
this.close();
return;
}
this.open();
}
} else {
if (leftPastCenter) {
if (positiveDelta) {
this.close();
return;
}
this.open();
return;
}
this.close();
}
}
}
Простейшим часть вытаскивать реализуется, если isScrolling
правда, никогда ничего не происходит. Это сразу же избавляется от одного уровня вложенности:
// above same
if (isScrolling) { return; }
if (isPastHalf) {
if (direction) {
this.close();
} else {
if (leftPastCenter && isPulled) {
this.close();
return;
}
this.open();
}
} else {
if (leftPastCenter) {
if (positiveDelta) {
this.close();
return;
}
this.open();
return;
}
this.close();
}
}
Теперь рассмотрят случаи this.open()
называется. Если isPastHalf
истинно, this.open()
вызывается только тогда, когда !direction
и !(leftPastCenter && isPulled)
.Если isPastHalf
ложно, то this.open()
вызывалась только когда leftPastCenter
и !positiveDelta
:
// above same
if (isScrolling) { return; }
if (isPastHalf) {
if (!direction && !(leftPastCenter && isPulled)) {
this.open();
} else {
this.close();
}
} else {
if (leftPastCenter && !positiveDelta) {
this.open();
} else {
this.close();
}
}
Подавать сослагательное наклонение (так this.close()
приходит первым), делает код немного аккуратнее, и дает мой окончательный вариант:
function() {
var duration = +new Date() - start.time,
isPastHalf = Number(duration) < 250 && Math.abs(delta.x) > 20 || Math.abs(delta.x) > viewport/2,
direction = delta.x < 0,
leftPastCenter = this.content.getBoundingClientRect().left > viewport/2,
positiveDelta = this.isEmpty(delta) || delta.x > 0,
isPulled = pulled === true; // I'll assume the test is needed rather than just using pulled.
if (isScrolling) { return; }
if (isPastHalf) {
if (direction || (leftPastCenter && isPulled)) {
this.close();
} else {
this.open();
}
} else {
if (!leftPastCenter || positiveDelta) {
this.close();
} else {
this.open();
}
}
}
Мне сложно делать больше, не зная своей кодовой базы. Стоит отметить direction
, и моя новая переменная positiveDelta
почти идентична - вы можете удалить positiveDelta
и просто использовать direction
. Кроме того, direction
не является хорошим именем для логического, что-то вроде movingLeft
было бы лучше.
Что именно вы задаете эту ошибку? – marekful
Серьезно? Не используйте вложенные 'if'. Выполните обязанности в соответствии с принципом единоличной ответственности *. Один кусок кода (модуль) должен делать одно и только одно, и он должен делать это хорошо. Просто подумайте о том, сколько возможных путей выполнения делают эти уродливые if-кусты ... – Powerslave
Вы читали код @Powerslave? Как это нарушает SRP? – Joe