在计算链逻辑表达式 JavaScript 时出现意外结果

unexpected results in evaluation of chains logical expressions javascript

本文关键字:意外 结果 JavaScript 表达式 计算      更新时间:2023-09-26

我正在编写一个程序,根据此代码中列出的标准来识别特殊数字 战争 kata:

http://www.codewars.com/kata/catching-car-mileage-numbers

这是我的完整代码和测试的链接:

http://www.codeshare.io/UeXhW

我已经对我的函数进行了单元测试,这些函数测试了每个特殊数字条件,它们似乎按预期工作。但是,我有一个功能:

function allTests(number, awesomePhrases){
  var num = number.toString().split('');
  // if any criteria is met and the number is >99 return true
  return number > 99 && (allZeros(num) || sameDigits(num) || incrementing(num) || decrementing(num) || palindrome(number) || matchPhrase(number, awesomePhrases)) ? true : false;
}

它确定是否满足成为特殊号码的任何标准,并且没有按预期工作。例如,当我在 7000 上测试 allZeros() 函数时,它返回了 true,但 alltests(7000) 返回了 false。关于如何评估逻辑表达式链,是否有我不理解的东西,或者问题是别的什么?

我已经查看了W3schools和MDN来尝试诊断问题。

将所有的 !== 更改为 != 就可以了。

只要 allTests() 使用第二个参数执行,即使它是空字符串,也会产生错误的结果,如下所示:

allTests(7000,"");

如果仅使用一个参数(即数字)调用函数,则会出现此错误:

捕获的类型错误:无法读取未定义的属性"长度"

错误消息指的是逻辑链中的一个函数,即 matchPhrase(),它需要两个参数:numberawesomePhrases。如果使用 null 而不是提供空字符串,则也会收到相同的错误消息。

JavaScript不支持默认参数的概念 - 至少不是以人们可能期望的方式;参数默认为undefined。 但是有一种方法可以绕过这个障碍并改进代码,以便可以避免这种不必要的错误。 只需更改 matchPhrase(),如下所示:

   function matchPhrase(number, awesomePhrases){
      awesomePhrases = typeof awesomePhrases !== 'undefined' ?  awesomePhrases : "";
      for(var i = 0, max=awesomePhrases.length; i < max; i++){
        if(number == awesomePhrases[i]){
          return true;
        }
      }
      return false;
   }

第一个语句接受第二个参数的值,只要它不是未定义的值;如果是这样,则变量设置为空字符串。(技术来源:这里)。

为了使代码更容易理解,我建议按如下方式重写 allTests(),以便代码遵循更明确的自我记录样式:

    function allTests(number, awesomePhrases){
      var arrDigits = number.toString().split('');
  // if any criteria is met and the number is >99 return true
  return number > 99 && (allZeros( arrDigits ) || sameDigits( arrDigits ) || incrementing( arrDigits ) || decrementing( arrDigits) || palindrome(number) || matchPhrase(number, awesomePhrases)) ? true : false;
    }

此函数接受一个数字,并使用其 toString() 方法将该数字转换为字符串。 不可见的结果字符串将在空字符串上拆分自身,以便arrDigits的结果是一个数字字符串数组,每个字符串仅包含一个数字。这是随之而来的 allZeros() 问题的起源点,它将字符串化数字与数字进行比较。

顺便说一下,在函数 allTests() 中有一个非常长的三元表达式。 语法很好,但您可能希望按如下方式重写代码:

  function getCriteriaStatus(arrDigits,number,awesomePhrases) {
    var criteria = new Array(); 
    criteria[0] = allZeros( arrDigits );
    criteria[1] = sameDigits( arrDigits );
    criteria[2] = incrementing( arrDigits );
    criteria[3] = decrementing( arrDigits);
    criteria[4] = palindrome(number);
    criteria[5] = matchPhrase(number, awesomePhrases);
    var retval = false;
    for (var i=0, max=6; i < max; i++) {
          if ( criteria[i] == true ) { 
              retval = true;
              break;
          }
    }
    return retval;
 }
function allTests(number, awesomePhrases){
  var arrDigits = number.toString().split('');
  var criteria_met = getCriteriaStatus(arrDigits,number,awesomePhrases);
  return (number > 99 && criteria_met);
}

为了在调用 allZeros() 时从 allTests() 获得所需的真实结果,而不是使用 parseInt() 使代码复杂化,我建议重写 allZeros() 和任何其他包含代码的函数,这些代码通过将数字字符串值与数字进行比较,方法是从标识运算符更改为相等运算符。 更改仅涉及用==替换===以及用!=替换!==。 使用标识运算符比较相同数据类型的值的代码,这些运算符可能并且可能应该保持不变。(见这里)。