【问题标题】:Why array reserves so many spaces even with string key?为什么即使使用字符串键,数组也会保留这么多空格?
【发布时间】:2013-02-19 03:52:19
【问题描述】:

我有以下数组:

var arr = [];
console.log(arr.length); //Output: 0

arr["1231321"] = "abcd";
console.log(arr.length); //Output: 1231322

arr["1231321".toString()] = "abcd";
console.log(arr.length); //Output: 1231322

arr["a1231321"] = "abcd";
console.log(arr.length); //Output: 0

arr["1231321a"] = "abcd";
console.log(arr.length); //Output: 0

这里是小提琴:http://jsfiddle.net/HcrcR/

当我将我的 arr 更改为 var arr = {}; 时,它就可以工作了。

但是,即使我使用字符串键,它也开始从键中推送数据,这是什么原因呢?

【问题讨论】:

  • 你有一个数组。当你使用arr["key"](非数字键......字符串仍然被转换)时,你正在设置属性,这与它的内容/长度无关
  • 当你使用: var arr = {} 你有一个使用键/值对的对象。

标签: javascript arrays hashmap


【解决方案1】:

我有以下数组/哈希图:

这是一个 JavaScript 术语中的Array

var arr = [];
console.log(arr.length); //Output: 0

这是预期的,它是一个空数组。

arr["1231321"] = "abcd";
console.log(arr.length); //Output: 1231322

length 属性如此之大的原因是它总是+1 而不是最高索引。使用字符串并不重要,Arrays 和 Objects 的键在 JavaScript 中始终是字符串。

此 Array 对象的长度属性是一个数据属性,其值在数值上始终大于名称为数组索引的每个可删除属性的名称。

Source

arr["1231321".toString()] = "abcd";
console.log(arr.length); //Output: 1231322

在字符串上调用toString() 不会做任何事情(它已经是一个字符串)。

arr["a1231321"] = "abcd";
console.log(arr.length); //Output: 0

同样,您在Array 上设置了一个看起来不像索引的属性。

arr["1231321a"] = "abcd";
console.log(arr.length); //Output: 0

见上文。字符串内部没有解析来尝试获取数字。

当我将我的 arr 更改为 var arr = {}; 时,它就可以工作了。

这就是对象在 JavaScript 中的工作方式。它们只是一串值的字符串键。

【讨论】:

  • 那么我们可以说,当我们使用数组时,JS尽可能将字符串键转换为数字。但是当我们创建一个对象时,它会使用自己的类型来保存键
  • @Vury JavaScript 键始终是字符串,即使对于数组也是如此。
【解决方案2】:

Array != Object (or hashmap) 在 JavaScript 中。因此,添加到数组中的不是整数索引的属性不会影响Array.length

注意这里没有预留空间,仅仅因为长度是1231321,并不代表所有的空间都被分配了,JavaScript数组不必使用连续内存,如果是的话通常也不需要疏。实际上,它们只是作为优化的连续性,并且默认行为是它们就像对象一样是哈希映射。

如果你需要知道一个对象拥有的所有键,你需要使用https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys

但是,您不应该混合使用这两个概念,在 JS 中,您应该使用数组(数字索引)或对象(任何索引)

当你这样做时

arr["1231321"] = "abcd";

一样
arr[1231321] = "abcd";

这会影响数组的length。然而,

arr["1231321a"] = "abcd"

不创建新的数组索引(只是一个新的对象属性)并且不影响length 属性

请注意,如果您一个接一个地键入以下命令,则您的问题中的示例不正确

arr = [];
arr["1231321"] = "abcd";
console.log(arr.length); //Output: 1231322
arr["a1231321"] = "abcd";
// Output: 1231322, should be the same as before, not undefined
console.log(arr.length); //Output: 1231322

http://jsfiddle.net/tWCa4/

【讨论】:

  • 但是,你不应该混淆这两个概念,很高兴你提到了这一点,这对于避免混淆非常重要:)
【解决方案3】:

它可以使用您的前 2 个字符串作为索引,因为它们可以被解析为数字。

当您将无法解析为整数的内容传递给它时,数组会将其附加为数组的属性,而不是条目。

当您将其定义为对象时,它将充当对象并将所有内容视为字符串属性。长度将始终定义为 javascript 中数组的最大值+1。

说清楚

var x = [] 

创建一个新的Array,它将尝试将其输入解析为整数并将它们添加到数组中,否则会将它们分配为属性。

var x = {}

将创建一个 Object,它作为一组无序的属性工作,并且没有长度,除非您自定义定义 x.length = y,在这种情况下,它只是另一个没有特殊含义的属性。

【讨论】:

  • 我没有投反对票,但第一行不是真的,没有数字转换。
  • 也不是拒绝投票者,但没有强制转换为数字,Array 所做的是查看所有键,并将看起来像整数的键视为整数
  • 是的,铸造不是正确的术语。谢谢你的解释。我不在乎投反对票,我想要准确:) 我的更新看起来更好吗?
猜你喜欢
  • 1970-01-01
  • 2022-06-30
  • 2013-12-13
  • 1970-01-01
  • 1970-01-01
  • 2021-07-14
  • 1970-01-01
  • 2019-12-04
  • 2021-12-22
相关资源
最近更新 更多