Странное поведение с оператором else if (javascript)

Насколько я могу судить, код нормально работает, но когда добавляется или редактируется дополнительная информация, оператор if else начинает вести себя странно. Он правильно читает процентное значение, но не возвращает правильную буквенную строку.

var total = function (){
    var earned = 0;

     for(i = 0; i < Assignments.length; i++){
         earned += parseInt(Assignments[i].earned);
     }
     var possible = 0;

     for(i = 0; i < Assignments.length; i++){
         possible += parseInt(Assignments[i].possible);
     }
     var percent = (Math.floor((earned/possible) * 100));

     console.log(percent);

  //grade letter

      if (percent >= 90){
         grade.innerHTML = '';
         grade.innerHTML = 'A ' + percent + '%';
      } else if (percent <= 89 && 80 >= percent){
         grade.innerHTML = '';
         grade.innerHTML = 'B ' + percent + '%';
      } else if (percent <= 79 && 70 >= percent){
         grade.innerHTML = '';
         grade.innerHTML = 'C ' + percent + '%';
      } else if (percent <= 69 && 60 >= percent){
         grade.innerHTML = '';
         grade.innerHTML = 'D ' + percent + '%';
      } else if(percent <= 59 && 0 >= percent){
         grade.innerHTML = '';
         grade.innerHTML = 'F ' + percent + '%';
      } else {grade.innerHTML = '';}



};

После нескольких вводов он вернет что-то вроде этого:

B = 73%? Нет!

Я думаю, что это может быть конфликтующие операторы else if, но, честно говоря, я понятия не имею, почему это так себя ведет.


person ShadowMorphyn    schedule 08.12.2014    source источник
comment
что конфликтует? Что возвращается, чего вы не хотите? Как именно все идет не так?   -  person Amit Joki    schedule 08.12.2014
comment
Почему бы вам не использовать оператор switch? Его намного легче читать, чем множество блоков if/else. w3schools.com/js/js_switch.asp   -  person WhiteBr0wnie_24    schedule 08.12.2014
comment
@ WhiteBr0wnie_24 Как вы используете переключатель с диапазонами номеров?   -  person JJJ    schedule 08.12.2014
comment
Я согласен, вам лучше использовать переключатель, это обычно работа переключателя. Любое обходное решение if/else было бы действительно позорным по сравнению с переключением :)   -  person enguerranws    schedule 08.12.2014
comment
Просто используя те же выражения, что и он, используя переключатель (процент): в диапазонах целых чисел в javascript"> stackoverflow.com/questions/5619832/   -  person enguerranws    schedule 08.12.2014
comment
switch(percent) не будет работать, когда percent равно 0 (должно быть switch(true)). И я бы не назвал это работой переключателя, когда вы взломаете его таким образом. Есть лучшие способы проверки диапазона чисел, чем цепочки else-if, но переключатель не входит в их число.   -  person JJJ    schedule 08.12.2014
comment
@Juhana просто делает это с помощью switch (boolean_expression), где логическое выражение может быть любым, которое оценивает true или false. Это тоже что-то вроде падежа (класс › 10 && класс ‹ 20). Посмотрите на мой ответ, я разместил интересную ссылку, где это можно прочитать.   -  person WhiteBr0wnie_24    schedule 08.12.2014
comment
@Юхана и др. др.: Хотя возможно использовать для этого switch в JavaScript (stackoverflow.com/a/17145931/ 157247, см. №3), это просто многословный else if.   -  person T.J. Crowder    schedule 08.12.2014
comment
@Juhana Итак, какие способы проверки диапазона чисел лучше, чем цепочки else-if?   -  person enguerranws    schedule 08.12.2014
comment
Увидев второй ответ на этот вопрос (stackoverflow.com/questions/5619832/), это могло бы сделать этот код более читабельным и эффективным.   -  person enguerranws    schedule 08.12.2014
comment
В ответе @enguerranws ​​TJ есть один хороший метод (или, в более общем случае, объект/массив, который вы повторяете). Метод switch(true) точно такой же, как и цепочка else-if, только с регистром вместо else if.   -  person JJJ    schedule 08.12.2014


Ответы (3)


У вас есть сравнения назад в else if, вы используете 70 >= percent, а не percent >= 70 (и так далее).

Отдельно нет причин присваивать '' innerHTML, если вы собираетесь присвоить ему что-то еще, и нет причин повторять верхнюю границу (percent <= 89 и т. д.), потому что вы используете else if, поэтому ветвь percent >= 90 будет иметь уже соблюдено. Повторение их также является проблемой обслуживания (вы измените одно, но забудете изменить другое).

So:

if (percent >= 90) {
    grade.innerHTML = 'A ' + percent + '%';
} else if (percent >= 80) {
    grade.innerHTML = 'B ' + percent + '%';
} else if (percent >= 70) {
    grade.innerHTML = 'C ' + percent + '%';
} else if (percent >= 60) {
    grade.innerHTML = 'D ' + percent + '%';
} else if (percent >= 0) {
    grade.innerHTML = 'F ' + percent + '%';
} else {
    grade.innerHTML = '';
}

Или, конечно, вы можете использовать карту, так как границы вашего класса делятся на 10 без остатка:

// Somewhere central
var grades = {
    6: 'D',
    7: 'C',
    8: 'B',
    9: 'A',
    10: 'A'
};

// ...then simply:
if (percent >= 0) {
    grade.innerHTML = (grades[Math.floor(percent / 10)] || 'F') + ' ' + percent + '%';
} else {
    grade.innerHTML = "Less than 0?!";
}

var grades = {
    6: 'D',
    7: 'C',
    8: 'B',
    9: 'A',
    10: 'A'
};

function showGrade(percent) {
  var grade;
  if (percent >= 0) {
    grade = (grades[Math.floor(percent / 10)] || 'F') + ' ' + percent + '%';
  } else {
    grade = "Less than 0?!";
  }
  snippet.log(grade);
}

var n;
for (n = 0; n <= 100; ++n) {
  showGrade(n);
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

person T.J. Crowder    schedule 08.12.2014
comment
Решение карты - лучшее ИМХО. - person enguerranws; 08.12.2014

If-Else диапазон условий выглядит неправильно, попробуйте этот код...

var total = function (){
var earned = 0, possible = 0;
for(i = 0; i < Assignments.length; i++){
     possible += parseInt(Assignments[i].possible);
     earned += parseInt(Assignments[i].earned);
 }
 var percent = (Math.floor((earned/possible) * 100));

 console.log(percent);

  //grade letter

  if (percent >= 90){
     grade.innerHTML = 'A ' + percent + '%';
  } else if (percent >= 80 && percent <= 89){
     grade.innerHTML = 'B ' + percent + '%';
  } else if (percent >= 70 && percent <= 79){
     grade.innerHTML = 'C ' + percent + '%';
  } else if (percent >= 60 && percent <= 69){
     grade.innerHTML = 'D ' + percent + '%';
  } else if(percent >= 0 && percent <= 59){
     grade.innerHTML = 'F ' + percent + '%';
  } else {grade.innerHTML = '';}
};

Хотя я оптимизировал некоторый код, мне не нужны 2 цикла, вы можете суммировать переменные earned, possible в одном цикле, и не нужно .innerHTML = '' при присвоении значения элементу.

person Girish    schedule 08.12.2014

Я нашел хороший пост об эффективности с использованием различных методов сравнения вещей. Я по-прежнему предлагаю использовать блок-переключатель вместо if/else, но технически это не лучше, чем ваше решение, но, как мне кажется, его приятнее читать. Вот фрагмент кода:

switch (true) {
case (0 <= val &&  val < 1000): /* do something */ break;
case (1000 <= val &&  val < 2000): /* do something */ break;
...
case (29000 <= val &&  val < 30000): /* do something */ break;
}

Взято из этого поста. Также есть интересная таблица (в первом ответе) less-than и различные методы выполнения этой работы. Я знаю, что на самом деле это не решение для вашего ответа, но оно может пригодиться, если вам нужно добавить больше if/else и делать огромные списки со значениями.

person WhiteBr0wnie_24    schedule 08.12.2014
comment
Повторение границ делает это широко открытым для ошибок обслуживания. Но вы можете сделать то же самое, без повторения границ, в JavaScript switch случаи оцениваются по порядку, и выполняется только первый совпавший (как в случае else if). - person T.J. Crowder; 08.12.2014