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

Javascript - Why are function calls inside boolean expressions evaluated first?

我将从我的问题的一个简化示例开始。

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));

以上函数return数组中模式出现的总次数,在某个连续限制后开始计数。它们是我的实际函数的简化示例,我只想在 i < len.

时评估 arr[i].charCodeAt(0) === 49 这样的表达式

foo 函数按预期工作,但如果我像在 bar 中那样在我的 while 条件中包含一个函数调用,它首先被评估,并抛出一个 TypeError 尝试评估未定义的索引.

我可以在 另一个 i<len检查之前将该表达式移动到 do-while 循环中。我想知道为什么函数优先于 "left-to-right" 评估,如果有其他我可以做的事情来防止它。

it throws a TypeError trying to evaluate an undefined index.

因为 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));

您 运行 已超出索引。但是为什么 bar() 会引发异常而 foo() 不会呢?因为 javascript returns "undefined" 类型的对象在 out-of-index 上。但是该对象没有方法 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
}