在javascript中我定义了一个这样的数组
var arr = [1,2,3];
我也能做到
arr[-1] = 4;
现在,如果我这样做
arr = undefined;
我也失去了对 arr [-1] 的价值的引用。
对我而言逻辑上似乎arr [-1]也是 arr 的一部分。
但是当我关注时(没有设置未定义的arr)
arr.length;
返回 3 而非 4 ;
所以我的观点是如果数组可以与负索引一起使用,这些负数索引也应该是它们长度的一部分**。 我不知道可能是我错了,或者我可能错过了关于数组的一些概念。
答案 0 :(得分:81)
对我而言逻辑上似乎arr [-1]也是arr的一部分。
是的,但不是你想象的那样。
您可以将任意属性分配给数组(就像JavaScript中的任何其他对象一样),这是您在-1
处“索引”数组并分配值时所执行的操作。由于这不是数组的成员而只是一个任意属性,因此您不应期望length
考虑该属性。
换句话说,以下代码执行相同的操作:
var arr = [1, 2, 3];
arr.cookies = 4;
alert(arr.length) // 3;
答案 1 :(得分:20)
length
属性将返回比最高分配“索引”高一的数字,其中数组“索引”是大于或等于零的整数。请注意,JS允许“稀疏”数组:
var someArray = [];
someArray[10] = "whatever";
console.log(someArray.length); // "11"
当然,如果没有元素,则length
为0
。另请注意,如果您使用length
删除最高元素,则delete
不会更新。
但是数组是对象,因此您可以使用其他任意属性名称分配属性,包括负数或分数:
someArray[-1] = "A property";
someArray[3.1415] = "Vaguely Pi";
someArray["test"] = "Whatever";
请注意,即使您提供类似-1
的数字,JS也会将属性名称转换为字符串。 (正整数索引也成为字符串。)
数组方法(如.pop()
,.slice()
等)仅适用于零或更高整数“索引”,而不适用于其他属性,因此length
是一致的那一点。
答案 2 :(得分:6)
请注意,当您使用位置(或0)索引时,值将放在数组中:
var array = [];
array[0] = "Foo";
array[1] = "Bar";
// Result: ["Foo", "Bar"]
// Length: 2
添加非索引值(不是0-9 +)时不是这种情况:
var array = [];
array[0] = "Foo";
array[1] = "Bar";
array[-1] = "Fizzbuzz"; // Not a proper array index - kill it
// Result: ["Foo", "Bar"]
// Length: 2
按规则播放时,值只会放在数组中。如果不这样做,则不接受。然而,它们在Array对象本身上被接受,这与JavaScript中的任何内容都是如此。即使["Foo", "Bar"]
是我们数组中唯一的值,我们仍然可以访问"Fizzbuzz"
:
array[-1]; // "Fizzbuzz"
但请注意,这不是数组值的一部分,因为它的“索引”无效。它被添加到数组上作为另一个成员。我们可以以相同的方式访问其他数组成员:
array["pop"]; // function pop() { [native code] }
请注意,我们正在访问数组上的pop
方法,该方法通知我们这包含本机代码。我们没有使用“pop”键访问任何数组值,而是访问数组对象本身的成员。我们可以通过循环对象的公共成员来进一步确认这一点:
for (var prop in array)
console.log(prop, array[prop]);
其中吐出以下内容:
0 Foo
1 Bar
-1 Fizzbuzz
再次,
很棒的问题!导致我确实做了双重拍摄。
答案 3 :(得分:5)
如果您确实希望将负索引和其他索引包含在长度中,请自行创建功能:
function getExtendedArray() {
var a = [];
Object.defineProperty(a, 'totalLength', {
get : function() { return Object.keys(a).length; }
});
return a;
}
然后例如:
var myArray = getExtendedArray();
console.log(myArray.totalLength); // 0
myArray.push("asdf");
myArray[-2] = "some string";
myArray[1.7777] = "other string";
console.log(myArray.totalLength); // 3
答案 4 :(得分:3)
JavaScript中的数组实际上是对象。它们只是从Array构造函数原型。
数组索引实际上是散列映射中的键,所有键都转换为字符串。您可以创建任何键(即“-1”),但Array上的方法可以调整为像数组一样。所以length
不是对象的大小,而是仅保证大于最大整数索引。同样,打印arr
只会列出带整数键> = 0的值。
答案 5 :(得分:1)
根据MDN:
length属性的值是一个带有正号的整数,值小于2到32次幂(232)
在Javascript中,您可以在您创建的任何对象上设置属性。
var array = new Array();
array = [1,2,3];
array["boom"] = "pow";
以同样的方式设置负索引时,它将其存储为数组中的属性而不是索引的一部分。
array[-1] = "property does not add to array length";
这就是为什么长度不反映它,但是for..in循环显示它。
答案 6 :(得分:1)
Array 只是JS中一种特殊的 Object 对象。有一个特殊的语法,这很好,因为它使我们可以有效地使用它们。想象这样写一个数组文字将是多么乏味:
const array = {{0: 'foo'}, {1: 'bar'}, {2: 'baz}} //etc...
但是还是有物体。因此,如果您这样做:
const myArray = [42, 'foo', 'bar', 'baz'];
myArray[-1] = 'I am not here';
myArray['whatever'] = 'Hello World';
这些非整数属性将附加到对象(数组是哪个)上,但是无法通过Array.length
之类的本机方法访问。
您可以假定本机的“长度”方法是一种吸气剂,该方法对所有可转换为正数的属性(和索引 are 属性,而值是实际的值)进行计数整数或零。像这样的伪实现:
const myArray = {
'-1': 'I am not here', // I have to use apostrophes to avoid syntax error
0: 42,
1: 'foo',
2: 'bar',
3: 'baz',
whatever: 'Hello World',
myLength() {
let counter = 0;
for (let prop in this) {
let toInt = parseInt(prop, 10);
if (!Number.isNaN(toInt) && toInt > -1) {
// If you're not an integer, that's not your business! Back off!
counter += 1;
}
}
return counter;
}
}
console.log(myArray.myLength()); // 4
答案 7 :(得分:0)
当您使用非正数或非数字索引时,数组表现为具有键值对的关联数组。
要遍历数组,您可以使用
for(var index in myArray) {
document.write( index + " : " + myArray[index] + "<br />");
}