为什么JS允许在数组中使用负数索引?

3
为什么JS中的数组负索引不会引发错误?看起来数组中没有意图使用负索引元素:
- `array.length` 不计算具有负索引的元素。 - `array.forEach()` 不迭代具有负索引的元素。
更新。问题不是“为什么技术上可能”,而是“为什么设计上允许”。
【已解决】简短回答:没有特别的原因,它只是这样发生了。

4
数组是一种“奇特”的对象,任何键都可以使用。 - Nina Scholz
负数索引实际上不像真正的索引那样起作用。 - palaѕн
3个回答

5

数组是JavaScript中的一种特殊类型对象。它有额外的方法和属性列表(例如.length.forEach),并且它还有一组使用的索引(整数正数从零开始)。但与任何其他对象一样,它可以具有附加属性:

var arr = ['A', 'B'];
arr.extra = 'C';
console.log(arr[0], arr[1], arr.extra); // A B C

由于对象属性不仅可以通过点号访问,还可以通过方括号访问,因此您可以使用类似数组的语法访问任何属性:

var obj = { extra: 'D' };
console.log(obj['extra']); // D
console.log(arr['extra']); // C

你可以使用相同的语法来分配属性:

obj['x'] = 'E';
obj[33] = 'F';
arr['y'] = 'G';
arr[-1] = 'H';
console.log(obj.x, obj[33], arr.y, arr[-1]); // E F G H

你可以放心使用数字作为对象属性名,它会自动转换为字符串。 唯一的区别在于,当您使用正整数值作为属性名时,它们将被解释为数组索引。
var arr = [];
arr[0] = 'A';
arr[1] = 'B';
arr[-1] = 'C';
arr.forEach(value => console.log(value)) // A, B
console.log(arr.length); // 2
console.log( Object.keys(arr) ); // ["0", "1", "-1"]

好的,我明白它在技术角度上是如何工作的,这是有道理的。 但是,这还是会引起困惑和不安,因为JS参考中指出实现强制整数作为索引(键),可能是为了给对象行为增加更多的"数组性"。但是,显然它并没有强制索引为非负数,这是"数组性"的另一个属性,对我来说这看起来是不连贯的。除非我理解错了。 - Dixie Flatline
就是这样。JavaScript并不是最可预测的语言。然而,它始终能正常工作。你只需要了解更多边缘情况,以确保代码的安全性。 - termosa
1
哦,我看过了UPD。所以你知道,JavaScript的设计并不是十分完善,因为它几乎是由一个开发者在短期内开发出来的。也就是说,并不是每个JavaScript的特性都经过计划,有时只是代码中的一个if语句“只是为了让它工作”。而且这些特性一直被保留至今,为了不破坏向后兼容性。 - termosa

1
在JavaScript中,数组也可以作为哈希对象使用(与js中的几乎所有对象(包括函数)一样)。因此,执行:a[-1] = -1只是在数组中定义了一个新的键(作为对象哈希表)并指定键值为"-1",值为-1
您应该知道,几乎所有JavaScript中的对象也可以用作哈希对象。这就是你看到的。但是,对于数组的这些键(它们不是正整数),不会按照正常的方式计算为数组键,而仅仅是哈希键

合理的观点,尽管JS参考指出:数组不能使用字符串作为元素索引(就像关联数组一样),而必须使用整数。所以有一种通用数组(称为关联数组),实际上是一个哈希表。我期望普通数组在其"数组性质"方面有更多的强制性,就像它对可能是索引值的内容所做的那样。 - Dixie Flatline
@DixieFlatline,当在js中将哈希键作为键传递时,它们会自动转换为字符串。因此,执行a[-1]="foo"实际上会被转换为a["-1"]="foo"。由于js中的所有对象都可以是哈希对象,所以会进行这样的转换。数组会检查它们的键是否为正整数,并以不同的方式处理,否则默认为哈希对象的功能。 - Nikos M.

0
JS允许在数组中使用负索引的简单原因是它们在底层是对象。你甚至可以使用[].blah = 5这样的语法,虽然合法但是不推荐。

1
我认为如果你需要同时使用数组和对象,这不是一个坏主意。这样你可以拥有一个实例具备两种行为。jQuery使用类似数组的对象作为实例,但如果你不需要另一个原型链,我认为真正的数组更好。 - Trop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接