如果未找到匹配项,为什么 indexOf 返回 -1?

Why is indexOf returning -1 if no match has been found?

str.indexOf(searchValue[, fromIndex])

The index of the first occurrence of searchValue, or -1 if not found.

- MDN web docs

如果在数组中找不到匹配项,为什么 -1.indexOf 选择为返回值?

console.log([].indexOf()) // -> -1

换成0不是更合适吗?这是有道理的,因为确实有 0 个匹配元素。这样我们就可以直接在条件语句中使用它,例如:

if( Array.indexOf(String) ) { ... }

而不是

if( Array.indexOf(String) !== -1 ) { ... }

这是为什么?有什么特别的原因吗?我在 Java、C++ 和 C 中看到了相同的情况。这是因为本机函数的设计方式吗?

Would it not be more suitable to have 0 instead?

没有。索引从零开始。

var str = "ABC";
console.log(str[0]);
console.log(str.indexOf("A"));

(数组也是如此,尽管引用了字符串文档,但您仍将其用于示例)。

因为在几乎所有编程语言中,0 都是数组的第一个位置。

indexOf() 给出元素在数组中的位置,数组的有效索引从 0, 1, ... 开始,依此类推直到 array.length-1 所以如果 indexOf() return 0 对于不存在的元素,那将是不正确的,因为 0 是一个有效的索引。因此使用-1

嗯。原因很简单。 indexOf returns 元素的位置不是它是否存在。另外,所有(99%)编程语言都是 0 索引,或者更好地说 stringsarrays 是 0 索引,这意味着第一个元素在位置 0.

将位置视为数组开头元素的 offset。所以从数组开始的第一个元素的 distance/offset 是 0 :)

也许您正在寻找 includes() 检查元素是否在数组中的方法。

const arr=[1,2,3]
// classic
if (!arr.includes(4)) {
  console.log('4 does not exist (classic)')
}

// or short circuit

!arr.includes(4) && console.log('4 does not exist (short circuit)')

// conditional (ternary) operator

!arr.includes(4) ? console.log('4 does not exist (ternary)') : ""

观察

此外,您不应将 indexOf() 用作布尔条件,因为例如

let arr=['a','b','c']

arr.indexOf('a') ? console.log('true') : console.log('false')

在上面的例子中,indexOf(a) returns 是位置 0。在布尔条件下,0 被 javaScript 视为假。所以它不会给你预期的结果。

其他人都在说同样的话,但让我尝试一下答案的另一种措辞。

在 Javascript 中,数组的索引从元素 0 开始。因此,如果在开头找到的字符串有效 return 值将为 0。如果未找到的字符串被报告为 0,您将不知道是没发现还是一开始就发现了。 -1 永远不是字符串中某个位置的有效值。

关于你的测试

if( Array.indexOf(String) ) { ... }

您可以改用

if( 1+Array.indexOf(String) ) { ... }

避免使用 !== -1 测试。

作为一般考虑,Array.indesOf() 的结果被重载了。结果包含函数结果和错误代码。这种重载允许在测试中直接使用函数调用。但是请考虑,如果函数调用在 if 语句中,您可能需要再次调用该函数,这是一种效率损失。如果在 if 之前对结果进行赋值,然后测试结果,您的计算效率会更高。甚至没有内存成本,因为函数中的变量在堆栈上,如果您将变量保留在本地,则函数 return 会清除堆栈。

returned 包含 success/fail 标志和结果的结构的函数是一种干净的方法,可以概括可能失败的函数调用,并且是一个方便的地方放置异常处理而不会使您想做的简单测试复杂化。