为什么 typeof 数组对象 返回的是 "object" 而不是 "array"?

262
为什么对象数组被认为是一个对象,而不是一个数组?例如:
$.ajax({
    url: 'http://api.twitter.com/1/statuses/user_timeline.json',
    data: { screen_name: 'mick__romney'},
    dataType: 'jsonp',
    success: function(data) {
        console.dir(data); //Array[20]
        alert(typeof data); //Object
    }
});​

小提琴


7
这就是 typeof 的定义,但你可以使用 Array.isArray - pimvdb
4
奇怪的是这个问题被标记为另一个问题的重复,而那个问题看起来完全不同... - ZAD-Man
2
这是因为在ECMAScript中唯一存在的“类型”是undefined、null、boolean、number、bigint、string、symbol和object。 - rosshjb
3个回答

373

在 JavaScript 中,一个奇怪的行为和规范是 typeof 数组的结果是 Object

你可以用以下几种方式来检查变量是否为数组:

var isArr = data instanceof Array;
var isArr = Array.isArray(data);

但最可靠的方法是:

isArr = Object.prototype.toString.call(data) == '[object Array]';

因为您在问题中标记了jQuery,您可以使用jQuery的isArray函数:

var isArr = $.isArray(data);

18
换句话说,typeof永远不可能返回"Array"这个结果吗? - Johan
18
但是最可靠的方法是:...所以你提出的其他方法不可靠吗? - Alex
16
@Alex,是的,如果你正在检查从<iframe>获取的数组,则其他人可能会给你“false”。 - gdoron
10
MDN似乎表明Array.isArray(…)应该是可靠的。请参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/instanceof#instanceof_and_multiple_context_(e.g._frames_or_windows)? - Mark Fox
3
@m,你说得对,但是在旧版的浏览器中不支持。请参见此处 - gdoron
显示剩余2条评论

39

引用规范:

15.4 数组对象

数组对象对一定类别的属性名称进行特殊处理。当且仅当ToString(ToUint32(P))等于P且ToUint32(P)不等于2^32-1时,属性名称P(以字符串值的形式)是一个数组索引。具有数组索引名称的属性也称为元素。每个数组对象都有一个长度属性,其值始终是小于2^32的非负整数。长度属性的值大于名称为数组索引的每个属性的名称;在创建或更改数组对象的属性时,必要时调整其他属性以保持此不变性。具体而言,每当添加一个名称为数组索引的属性时,如果需要,长度属性会更改为该数组索引的数字值加1;并且每当长度属性更改时,名称为数组索引且其值不小于新长度的每个属性都将自动删除。此约束仅适用于数组对象的自己的属性,并且不受可能从其原型继承的长度或数组索引属性的影响。

以下是关于typeof的表格:

enter image description here


为了补充一些背景,JavaScript中有两种数据类型:

  1. 原始数据类型 - 这包括null、undefined、string、boolean、number和object。
  2. 派生数据类型/特殊对象 - 这些包括函数、数组和常规表达式。是的,在JavaScript中,这些都派生自"Object"。

JavaScript中的对象与大多数面向对象语言中看到的关联数组/字典具有类似的结构——即它具有一组键值对。

可以将数组视为具有以下属性/键的对象:

  1. Length - 可以是0或以上(非负数)。
  2. 数组的索引。我指的是“0”、“1”、“2”等都是数组对象的属性。

希望这有助于更加清晰地解释为什么 typeof Array 返回一个对象。干杯!


5
根据 https://developer.mozilla.org/en-US/docs/Glossary/Primitive,此对象不是原始的。 - Potatoes

12
尝试这个示例,您将理解关联数组和JavaScript对象之间的区别。
关联数组:
var a = new Array(1,2,3); 
a['key'] = 'experiment';
Array.isArray(a);

返回 true

请注意,a.length 将会是未定义的,因为 length 被视为键名。你应该使用 Object.keys(a).length 来获取关联数组的长度。

对象

var a = {1:1, 2:2, 3:3,'key':'experiment'}; 
Array.isArray(a)

返回 false

JSON 返回一个对象……也可能返回一个关联数组……但它并不是这样的。


你能举一个关联数组和JSON的例子吗?就像这样:jQuery.parseJSON('{"name":"John"}')... 这个通常被认为是一个对象。你认为JSON如何表示关联数组? - Reflective
在 JSON 中并不存在你所谓的关联数组。但是我不确定你的回答与问题有何关联。 - pimvdb
但是这怎么回答问题呢?OP有一个数组,typeof返回"object"。他想知道为什么会这样。简而言之,问题是:为什么typeof []不返回"array"?你并没有真正回答那个问题。 - pimvdb
这里的JSON没有问题;data实际上是一个数组。OP根本没有使用关联数组。问题是为什么在数组上使用typeof会得到"object"。但我猜我们说的是不同的语言。 - pimvdb
无论如何...继续谈论那个已经没有用了 :) 让我们切换到“最新问题”频道吧 ;) - Reflective
显示剩余11条评论

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