33

数组仅仅是伪装的对象吗?为什么/为什么不?它们以什么方式(这样/不是)?

我一直认为 JS 中的数组和对象本质上是相同的,主要是因为访问它们是相同的。

var obj = {'I': 'me'};
var arr = new Array();
arr['you'] = 'them';

console.log(obj.I);
console.log(arr.you);
console.log(obj['I']);
console.log(arr['you']);

我误导/误会/错了吗?关于 JS 字面量、原语和字符串/对象/数组/等等,我需要了解什么?

数组/对象仅仅是变相的字符串吗?为什么/为什么不?它们以什么方式(这样/不是)?

4

7 回答 7

47

数组是对象。

但是,与常规对象不同,数组具有某些特殊功能。

  1. 数组在其原型链中有一个附加对象——即Array.prototype. 该对象包含可以在数组实例上调用的所谓数组方法。(方法列表在这里:http ://es5.github.com/#x15.4.4 )

  2. 数组有一个length属性(它是实时的,因此,它会自动更新)(在这里阅读:http: //es5.github.com/#x15.4.5.2

  3. 数组有一个关于定义新属性的特殊算法(在这里阅读:http: //es5.github.com/#x15.4.5.1)。如果您将新属性设置为数组,并且该属性的名称是可以强制转换为整数的字符串(如'1''2''3'等),则应用特殊算法(它在规范中的第 123 页定义)

除了这三件事之外,数组就像普通对象一样。

阅读规范中的数组:http: //es5.github.com/#x15.4

于 2011-02-19T02:38:21.197 回答
12

对象是从字符串键到值的无序映射,数组是值的有序列表(带有整数键)。这是主要的区别。它们都是非原始的,因为它们由多个值组成,这也意味着 JavaScript 中的引用传递。

不过,数组也是一种对象,因此您可以为它们附加额外的属性,访问它们的原型等等。

在您修改后的示例中,您只是利用了数组实际上是一个对象这一事实,即您可以在它们上设置任何属性。你不应该那样做。如果您不需要有序的值列表,请使用普通对象。

于 2011-02-19T02:14:47.673 回答
6

字符串可以是原始的也可以是对象,这取决于它们的声明方式。

var str = 'yes';

给你一个原始的,同时,

var str = new String('yes');

会给你一个 String 对象。


所有数组都是相同的(无论它们是否用 [] 或 new Array() 定义),都是对象类型,并且继承自“Array”对象的原型。Javascript 中没有真正的类,一切都是对象,并且有一个系统定义的对象,称为 Array。它有一个名为 'prototype' 的属性(对象类型),当您在具有原型属性的对象上使用 new 关键字时,它会创建一个引用原型内容的实例并将其存储在您的变量中。因此,您在 Javascript 中使用过的所有数组都是 Array 原型属性的对象和实例。

在任何情况下,尽管数组确实是对象,但由于它们有用的属性和功能(例如长度、切片、推送等),它们的行为类似于数组。

另一个注意事项,虽然我说没有课程,但当你这样做时:

console.log(Object.prototype.toString.call(your_object));

它会给你一个 [object Object] 形式的字符串。但有用的是,当您使用数组调用它时,您会得到 [object Array] 与提供 [object Function] 和许多其他系统定义类型的函数相同的函数,这有助于区分普通对象和数组(因为 typeof运算符将始终只返回字符串“对象”)。

试试这个

var a = Array;

并进入 firebug 并检查 a 的内容,尤其是它的“原型”属性。

编辑:稍微改变了措辞,更正确。事实上,当您使用 new 关键字时,它会创建一个引用原型对象的实例。因此,在实例声明之后对原型所做的任何更改仍会影响实例。

编辑:回答您最新修订的问题(数组/对象实际上是变相的字符串):不。正如我所解释的,它们是对象。字符串要么是原始类型,要么是对象类型(String 对象的实例),其中包含原始等效项作为其属性之一。

于 2011-02-19T02:20:07.547 回答
5

数组不是 Javascript 中的原语,它们是对象。关键区别在于,因此,当您将数组传递给函数时,它是通过引用而不是值传递的。

所以是的!数组是 javascript 中的对象,具有完整的 Array.prototype 和所有内容(尽管不要碰它......)

混淆来自于 javascripts 允许您以两种方式访问​​对象属性的事实:

myObj.attribute 或 myObj["attribute"]

真正使数组成为数组的原因与您存储数据的方式无关——任何对象都可以使用用于存储数组的语法来存储值——使数组成为数组的原因在于数组方法(例如 shift () 和 sort()) 是为 Array.prototype 定义的。

于 2011-02-19T02:11:55.213 回答
1

尝试简要说明我认为最重要的内容:数组有许多对象没有的方法。包含:

  • 长度
  • 流行音乐

声明为的对象var x = {foo:bar}无法访问 .length() 方法。它们都是对象,但数组是一种具有上述方法的超集。

我不觉得我在解释方面甚至接近于 Crockford 标准,但我试图简洁。

如果您想快速获得结果,请打开 Firebug 或您的 javascript 控制台并尝试 Array.prototype 和 Object.prototype 以查看一些详细信息

更新:在您的示例中,您声明一个数组,然后执行:

foo['bar'] = 'unexpectedbehaviour';

会产生意想不到的结果,并且不会在简单的循环中可用,例如:

var foo=[0,1];
foo['bar'] = 2;

for(var i=0;i<foo.length;i++){
    console.log(foo[i]);
}

//outputs: 
//0
//1

数组可以接受foo['bar']=xfoo.bar=y喜欢一个对象,但不一定可以像上面突出显示的那样循环。

并不是说您不能遍历对象的属性,只是在使用数组时,您正在使用该独特的功能,并且应该记住不要混淆。

于 2011-02-19T02:19:42.597 回答
1

在 JavaScript 中你有几种类型,其他的都是对象。JavaScript 中的类型有:布尔值、数字和字符串。还有两个特殊值,“null”和“undefined”。

所以这个问题“JavaScript 数组是一个对象吗?” 有点模棱两可。是的,JavaScript 数组是一个“对象”,但它不是“对象”的一个实例。JavaScript 数组是“Array”的一个实例。虽然,所有对象都继承自 Object;您可以在 MDC上查看继承链。此外,数组的属性与对象略有不同。数组具有.length属性。他们也有.slice(), .join(), 等方法。

Douglas Crockford 对语言的特性进行了很好的调查。他的调查讨论了您所询问的差异。此外,您可以阅读更多关于问题 #4559207 中的文字和构造函数之间的区别。

于 2011-02-19T02:55:48.227 回答
0

数组是对象,但具有专门的性质。对象是由键索引的值的集合(在 Javascript 表示法中,{'key': 'value'}),而数组是键是数字的对象(具有一些函数和属性)。当您使用循环时,它们之间的关键区别很明显for each——对象将遍历其属性中的所有值,而数组将返回键。这是一个 JSFiddle 的链接,演示了不同之处——请注意,for each使用数组的第一个返回索引,而不是值;相反,第二个for each返回这些键的实际值。

于 2011-02-19T02:40:54.680 回答