评估链逻辑表达式javascript的意外结果

时间:2015-01-11 00:00:09

标签: javascript

我正在编写一个程序,根据此代码中列出的标准识别特殊数字wata 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试图诊断问题。

2 个答案:

答案 0 :(得分:0)

将你所有的!==改为!=将会改变。

答案 1 :(得分:0)

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

allTests(7000,"");

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

  

未捕获的TypeError:无法读取未定义的属性“长度”

错误消息指的是逻辑链中的一个函数,即 matchPhrase(),它需要两个参数:数字 awesomePhrases 。如果不是提供空字符串,而是使用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;
   }

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

为了使代码更易于理解,我建议按如下方式重写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()和包含代码的任何其他函数通过从标识运算符更改为相等运算符,将数字字符串值与数字进行比较。此更改仅涉及将===替换为==以及将!==替换为!=。使用标识运算符比较相同数据类型的值的代码,这些运算符可能并且可能应该保持不变。 (见here)。