JavaScript中的关联数组与对象有何区别?

71

在我的脚本中需要创建一个哈希表,我在谷歌上搜索了一下。大多数人都建议使用JavaScript对象来实现。问题是哈希表中的某些键中有“.”。我可以很容易地使用关联数组创建这些键。

我不明白为什么关联数组不好。我看到的网站上第一件事就是提到了长度属性。

我来自Perl背景,我使用哈希表的最常见用法是获取值、检查键是否存在、删除键值对和添加键值对。如果这些是我的常见用法,我能否安全地使用关联数组?


2
你所说的关联数组是什么? - themel
6
注意,下面的回答中有几个忽略了键与内置方法冲突的问题:请参见http://www.devthought.com/2012/01/18/an-object-is-not-a-hash/。 - NickZoic
7个回答

106

在JavaScript中,对象是关联数组...它们没有分开的概念。您还可以安全地在键名中使用“.”,但只能使用括号表示法来访问值:

var foo = {}
foo['bar'] = 'test';
foo['baz.bin'] = 'value';

alert(foo.bar); // Shows 'test'
alert(foo['baz.bin']); // Shows 'value'

如果你已经在使用它们并且它们可用,则是安全的。


12
请注意,与PHP关联数组不同,对象属性未经排序,即您不能依赖它们的顺序。 - andig
2
我认为你不能将对象概括为关联数组,主要是因为对象没有实现关联数组所具有的方法(例如:map、reduce、filter等)。 - hlin117
@hlin117 - 关联数组(对象)也没有这些方法。只有普通数组才有这些方法。 - Justin Niessner
@JustinNiessner 在我的Node应用程序中,我有用于关联数组的map、reduce等函数。 - velop
问题在于 foo.length=0 - zeros-and-ones
如果使用JavaScript对象作为键值映射,必须考虑到像“constructor”、“toString”这样的键可能无法正常工作。例如,对于一个空对象x,x["constructor"]存在或者在a中“constructor”为true等。 - Alejadro Xalabarder

34

在JavaScript中,对象和数组基本上是一样的,只不过数组有一些神奇的功能(自动更新长度属性等)和适用于数组的原型方法。构造一个对象比使用关联数组要容易得多:

var obj = {"my.key": "myValue"};

对比。

var obj = [];
obj["my.key"] = "myValue";
因此,永远不要使用数组对象进行此操作,而只需使用常规对象。 一些功能:
var obj = {}; // Initialized empty object

删除一个键值对:

delete obj[key];

检查一个键是否存在:

key in obj;

获取键值:

obj[key];

添加一个键值对:

obj[key] = value;

1
@realtebo,对于这个问题没有一流的语法,如果需要,您可以为其创建一个函数。 - Esailija
2
这个答案中关于不使用数组作为关联数组的部分,因为它需要两行代码而不是一行,这是非常误导人的。这种构造并没有填充目标元素,它设置了一个数组的属性,就像@Dominic Goulet和NullUserException在同一时间所描述的那样,这是我认为正确的答案。它之所以表现得像关联数组(你可以引用obj["my.key"])的唯一原因是数组的属性是一个对象,而对象是Javascript最接近关联数组的东西。 - enigment
3
我认为在JS中说数组和对象是相同的东西是不正确的。我的意思是,按照这个标准,在JS中几乎所有的东西都可以看作是一个对象。与其他类型的对象一样,数组允许你设置任意属性。然而,单独的对象本身没有关于有序数据的概念。 - Jason Baker
1
不是说“对象和数组基本上是一样的东西”,而是数组就是对象(但反之则不然)。 - Ajedi32
1
@Esailija 打开你的浏览器JavaScript控制台并粘贴以下内容:([] instanceof Object)。你会得到true。现在尝试这个:(typeof [])。你会得到"object"。在JavaScript中,数组是对象。 - Ajedi32
显示剩余2条评论

19

因为JavaScript中不存在内置的关联数组。这就是为令人不满的原因。

事实上,当你使用像下面这样的东西:

theArray["a"] = "Hello, World!";

它只是创建了一个名为“a”的属性并将其值设置为“Hello, World!”。这就是为什么长度始终为0,以及为什么alert(theArray)的输出为空的原因。


当然,JavaScript 中有关联数组这样的东西。只是没有内置的关联数组概念。例如,闭包具有关联数组:http://docs.closure-library.googlecode.com/git/class_goog_structs_Map.html - Jason Baker
@JasonBaker OP指的是JavaScript(见标签),而不是Google libs。当然,在JavaScript中,您可以随心所欲地做任何事情,正如您所说,JavaScript中没有“内置”的关联数组这样的东西。我认为这很明显,但我会更新答案。 - Dominic Goulet

9

实际上,“关联数组”在ECMAScript中与“类似数组的对象”基本相同。在ECMAScript中,甚至数组也是对象,只是具有数字键(在后台仍然是字符串)和.length属性,以及一些来自Array.prototype的继承方法。

因此,Perl哈希和ECMAScript对象行为类似。您可能不知道,您不仅可以通过点访问对象属性,还可以使用括号和字符串访问,例如

var myObj = { foo: 42 };

myObj.foo; // 42
myObj['foo']; // 42

了解这一点后,您还可以使用带有.的键。

var myObj = { };
myObj['hello.foo.world'] = 42;

当然,你只能通过方括号符号访问该键。

8

如果需要,您可以在JavaScript对象(也称关联数组)的键名中使用 .;它们会被无问题地接受。 小缺点是您不能使用带有点的键的快捷符号,例如:

var x = {};
x['hello'] = 'there';
alert(x.hello);

使用`alert('there')`是完全可以的,会弹出一个包含'there'的警示对话框。但是如果你使用点操作符:

var x = {};
x['this.is'] = 'sparta';
alert(x.this.is);

由于JavaScript会在x对象中查找名为this的属性,但实际上该属性并不存在,因此将失败。只有this.is属性存在。


完全赞成用“THIS IS SPARTA”替换旧的Foo Bar - jaumebalust

3

没有关联数组。它只是一个对象。

foo.bar;    // Equivalent to...
foo["bar"]; // Looks like associative array.

为什么JavaScript允许两者?它们之间是否有任何实际区别? - EJoshuaS - Stand with Ukraine
为什么不允许两者同时使用呢?唯一的区别在于,您可以使用“数组表示法”来使用变量,例如,bar ='plugh'; foo [bar]将返回由foo.plugh引用的值。 - Dave Newton
除非我漏看了什么,否则这对我来说似乎非常冗余。- http://stackoverflow.com/questions/42513889/why-does-javascript-allow-array-syntax-to-access-properties - EJoshuaS - Stand with Ukraine
1
@EJoshuaS 我唯一的回应是“那又怎样?”点访问更清晰,括号访问允许其他结构。我不认为“冗余”有问题(用引号因为它们允许不同的用法)。¯_(ツ)_/¯ - Dave Newton

2
为了方便使用数据,对象和数组之间不应有任何区别。你可以把它想象成一个对象,也可以把它想象成一个关联数组。最终,你可以把所有东西都看作是数据
  • 对于PHP,[ ]接受0、1或多个项(数组),并且被称为关联数组。这就是PHP中的JSON:

    $data = ["message"=>[ "id"=>405, "description"=>"Method not allowed.", "detail"=>[]], "object" => []];

  • 对于JavaScript,{ }接受0、1或多个项(数组),并且被称为对象。这种数据格式是JSON:

    data = {"message": { "id":405, "description":"Method not allowed.", "detail" : {}}, "object" : {}};

我只把它们叫做数据。描述数据的最简单方法是JSON或其变体。

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