Node.js的数组实际上是哈希映射表吗?

10

令我惊讶的是,这段代码实际上在node.js中可以运行:

var arr = new Array();
// also works: var arr = [];
arr[0] = 123;
arr['abc'] = 456;
arr; // node.js: [ 123, abc: 456 ], chrome: [123]

我一直以为数组按顺序存储对象,只能通过整数键访问,就像C++中的std::vector。但是,在这里它的行为类似于map或对象。更令人困惑的是,相同的代码在chrome中按预期工作,返回一个仅有一个条目123的数组。我认为node.js和chrome javascript使用相同的内部引擎V8。这里到底发生了什么?


不,它们实际上是JavaScript数组,类型为“对象”! - adeneo
2
虽然 Chrome 控制台不会显示 456,但 arr.abc 仍将是 456。除非您明确访问变量或 console.log(arr),否则它不会在控制台中显示。console.log(arr) 将记录:[123, abc: 456]。基本上,这只是一个外观问题。 - Cerbrus
如果将其存储在abc下,那么这并不是真正的哈希映射。只是一个键/值数组。 - Alex W
3个回答

9
Javascript允许您动态地扩展对象,而Array作为一个对象,您也可以这样做。您所做的是向数组添加一个名为abc的新属性,并将其赋值为456
因此,您可以说Javascript中的每个对象都可以以某种方式用作哈希映射表。 编辑 看起来Chrome在转储Array对象时过滤了非数字属性,而Node则转储了每个用户定义的属性。在我看来,Node的方式更好,因为字母数字属性在for in语句中可用:
var a = [1];
a['abc'] = 2;
for (var i in a) {
    console.log(i);
}
// Prints:
// 0
// abc

是的,每个对象都可以用作哈希映射,但这不是问题所在。这只是变量显示上的不一致性。这就是为什么我撤销了编辑的原因,此外:这个“问题”实际上是特定于node.js的。 - Cerbrus
在我看来,这个问题的关键不在于 console.log() 是否显示它,而在于 Javascript 中数组/对象作为哈希表的行为。 - Carlos
你还没有解决这个问题:实际上这两个对象包含相同的键/值对,但是在 Node 和 Chrome 中它们的行为似乎有所不同。 - Cerbrus
那么,既然你把我回答的内容添加到了你的答案中,你能否考虑取消对我的回答的负评? - Cerbrus

7
答案是正确的,如果您试图显示数组的长度,则行为可能更容易理解。
var ar = []
ar[0] = 42
console.log(ar.length) // 1

ar[12] = 21
console.log(ar.length) // 13

ar['ab'] = 1
console.log(ar.length) // 13 (separate property, not in array)

ar[ar.length] = 33
console.log(ar.length) // 14

ar.push(55)
console.log(ar.length) // 15

console.log(ar) // display all items specified above
//[ 42, , , , , , , , , , , , 21, 33, 55, ab: 1 ]
// which in fact really is:
// [ 42, , , , , , , , , , , , 21, 33, 55] as array and 
// special property of array object - 'ab':1

3

虽然在控制台中只输入arr时,Chrome不会显示456,但arr.abc仍然是456

除非您明确访问变量或使用console.log(arr),否则它不会在控制台中显示。这将记录:[123, abc: 456]

基本上,这只是一个外观问题。当您只在控制台中输入变量时,Node.js会显示数组对象上的键/值属性,而Chrome仅显示“正常”的数组条目,尽管两个数组实际上具有相同的内容。


@Joel:这个回答解决了你的问题吗?还有什么不清楚的地方吗? - Cerbrus

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