JavaScript数组中的负索引是否会导致数组长度?

时间:2012-11-29 03:56:00

标签: javascript arrays

在javascript中我定义了一个这样的数组

var arr = [1,2,3];

我也能做到

arr[-1] = 4;

现在,如果我这样做

arr = undefined;

我也失去了对 arr [-1] 的价值的引用。

对我而言逻辑上似乎arr [-1]也是 arr 的一部分。

但是当我关注时(没有设置未定义的arr)

arr.length;

返回 3 而非 4 ;

所以我的观点是如果数组可以与负索引一起使用,这些负数索引也应该是它们长度的一部分**。 我不知道可能是我错了,或者我可能错过了关于数组的一些概念。

8 个答案:

答案 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"

当然,如果没有元素,则length0。另请注意,如果您使用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的值。

More info here.

答案 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 />");
}