Javascript - 为什么首先评估布尔表达式中的函数调用?

时间:2018-03-27 12:40:36

标签: javascript function boolean-expression

我将以我的问题的简化示例开始。



function foo(arr) {
  let limit = 1,
      count = 0;

  for (let i=0, len=arr.length; i<len;) {
    if (arr[i] === '0' || arr[i] === '1') {

      let start = i;
      do {
        if (i - start >= limit) {
          count++;
        }
        i++;
      } while (i < len && arr[i] === '0' || arr[i] === '1');
    } else {
      i++;
    }
  }
  return count;
}

function bar(arr) {
  let limit = 1,
      count = 0;

  for (let i=0, len=arr.length; i<len;) {
    if (arr[i] === '0' || arr[i].charCodeAt(0) === 49) {

      let start = i;
      do {
        if (i - start >= limit) {
          count++;
        }
        i++;
      } while (i < len && arr[i] === '0' || arr[i].charCodeAt(0) === 49);
    } else {
      i++;
    }
  }
  return count;
}

let arr = ['0', '2', '3', '0', '1', '0', '4', '2', '0'];
console.log(bar(arr));
console.log(foo(arr));
&#13;
&#13;
&#13;

上述函数返回数组中模式出现的总次数,在某个连续限制之后开始计数。它们是我实际功能的简化示例,我只想在arr[i].charCodeAt(0) === 49时评估i < len这样的表达式。

foo函数按预期工作,但是如果我在条件中包含一个函数调用,就像在bar中一样,它首先被计算,然后抛出一个 TypeError 试图评估一个未定义的索引

我可以在另一个 i<len检查之前在do-while-loop中移动该表达式。我想知道为什么函数优先于上面&#34;从左到右&#34;评估,如果还有别的办法可以防止它。

2 个答案:

答案 0 :(得分:3)

  

它会抛出一个TypeError,试图评估一个未定义的索引。

因为arr[9]不存在,只需输入一个控制台语句来检查相同内容。

<强>演示

function foo(arr) {
  let limit = 1,
      count = 0;

  for (let i=0, len=arr.length; i<len;) {
    if (arr[i] === '0' || arr[i] === '1') {

      let start = i;
      do {
        if (i - start >= limit) {
          count++;
        }
        i++;
      } while (i < len && arr[i] === '0' || arr[i] === '1');
    } else {
      i++;
    }
  }
  return count;
}

function bar(arr) {
  let limit = 1,
      count = 0;

  for (let i=0, len=arr.length; i<len;) {
    if (arr[i] === '0' || arr[i].charCodeAt(0) === 49) {

      let start = i;
      do {
        if (i - start >= limit) {
          count++;
        }
        i++;
        console.log(i);
      } while (i < len && arr[i] === '0' || arr[i].charCodeAt(0) === 49);
    } else {
      i++;
    }
  }
  return count;
}

let arr = ['0', '2', '3', '0', '1', '0', '4', '2', '0'];
console.log(bar(arr));
console.log(foo(arr));

<强>解释

您的陈述相当于写作

var a = 1;
var b = 2;
a < 1 && b < 2 || true; //return true
a < 1 && b < 2 || false; //return false

因为您使用了||在没有()的表达式中,除非前两个表达式为true,否则将对其进行评估。

使用()作为

  } while (i < len && (arr[i] === '0' || arr[i].charCodeAt(0) === 49));

<强>演示

function foo(arr) {
  let limit = 1,
      count = 0;

  for (let i=0, len=arr.length; i<len;) {
    if (arr[i] === '0' || arr[i] === '1') {

      let start = i;
      do {
        if (i - start >= limit) {
          count++;
        }
        i++;
      } while (i < len && arr[i] === '0' || arr[i] === '1');
    } else {
      i++;
    }
  }
  return count;
}

function bar(arr) {
  let limit = 1,
      count = 0;

  for (let i=0, len=arr.length; i<len;) {
    if (arr[i] === '0' || arr[i].charCodeAt(0) === 49) {

      let start = i;
      do {
        if (i - start >= limit) {
          count++;
        }
        i++;
        console.log(i);
      } while (i < len && (arr[i] === '0' || arr[i].charCodeAt(0) === 49));
    } else {
      i++;
    }
  }
  return count;
}

let arr = ['0', '2', '3', '0', '1', '0', '4', '2', '0'];
console.log(bar(arr));
console.log(foo(arr));

答案 1 :(得分:0)

你的索引用完了。但是为什么bar()会引发一个foo()没有的异常?因为javascript在索引之外返回“undefined”类型的对象。但是该对象没有方法charCodeAt()并且引发​​了异常。

let arr = ['a', 'b']                    // note there is no arr[2]

console.log(arr[2]);                    // undefined
console.log(arr[2] === undefined);      // true
try
{  console.log(arr[2].charCodeAt(0));
}
catch(e)
{  console.log(e.message);              // Cannot read property 'charCodeAt' of undefined
}