深入理解:数组索引工作方式背后的底层逻辑是什么?

Deep understanding: What is the underlying logic behind the way array indexes work?

我问这个问题的动机

对我来说,编程的快感在于对给定语言背后的逻辑的深刻理解使您能够 "just figure things out" 使用该逻辑。因此,当我偶然发现似乎缺少这种逻辑的东西时,我会很困扰。

索引的工作原理

这是我对使用数组索引的了解:

var fruit = ["Apple", "Orange", "Kiwi"]

fruit.length = 3 // returns the length of the fruit array

var rotten = fruit[2] //assigns the value "Kiwi" to the variable "rotten"

fruit[2] = "Melon" //changes the 3rd object in the array fruit from "Kiwi" to "Melon"
fruit[fruit.length] = "Melon" //adds a new object to the array fruit after "Kiwi"

逻辑有什么问题

所以我刚刚使用.length得到了我的水果数组长度为三的信息。接下来我想使用 var rotten = fruit[] 访问第三个对象。我的逻辑告诉我应该使用 var rotten = fruit[3] 来执行此操作。但是 returns 未定义,因为对象的索引为 0、1、2。

同样,我的直接想法是使用以下代码将对象添加到数组:fruit[fruit.length + 1] = "Melon" 因为我知道 .length 方法 returns "the number of the last object"在数组中。这当然不是实际情况,因为当考虑索引为 0、1、2 时,这实际上是 2。

我的问题

在不使用 1、2、3 而不是 0、1、2 索引数组的背后是否有更深层次的逻辑,从而使其 - 在我看来 - 更直观地理解和使用 Javascript 或这只是你应该了解我的心并接受而不寻找任何更深层次推理的东西吗?

在 Fortran 系列语言中,正如您所建议的,数组从 1 开始索引,因为这是标准的数学实践。在 Algol-60/PASCAL 语言家族中,程序员选择起始索引——它可以是 0、1 或其他任何值。在 BCPL 和 C 语言家族以及大多数现代语言中(明显排除了 Julia),数组索引从 0 开始。

多年来,人们发现采用单一约定很方便——当不同程序员编写的代码组合在一起时,PASCAL 风格的索引会造成混淆,最好选择一个起始索引并坚持使用它。

0 和 1 之间的实际选择是相当随意的,但许多 wise people 同意从 0 开始会使许多操作更简单,更不容易出错。例如,比较以下两个基于 0 的数组交错实现:

if(i % 2 == 0)
    a[i / 2] = 42;
else
    b[(i - 1) / 2] = 42;

和基于 1 的:

if(i % 2 == 1)
    a[(i + 1) / 2] = 42;
else
    b[i / 2] = 42;