Почему массив typeof с объектами возвращает объект, а не массив?

Возможный дубликат:
JavaScript: проверьте, является ли объект массивом ?

Почему массив объектов считается объектом, а не массивом? Например:

$.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
    }
});​

Скрипка


person Johan    schedule 21.10.2012    source источник
comment
Вот как определяется typeof, но вы можете использовать Array.isArray.   -  person pimvdb    schedule 21.10.2012
comment
Странно, что это помечено как дубликат другого вопроса, который выглядит совершенно иначе...   -  person ZAD-Man    schedule 08.11.2018
comment
Это связано с тем, что в ECMAScript существуют только типы undefined, null, boolean, number, bigint, string, symbol и object.   -  person jinbeom hong    schedule 04.03.2020


Ответы (3)


Одним из странных свойств и спецификаций в Javascript является тип массива 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);
person gdoron is supporting Monica    schedule 21.10.2012
comment
Другими словами, typeof никогда не может вернуть массив? - person Johan; 21.10.2012
comment
Но самый надежный способ: ... Значит, другие предложенные вами способы ненадежны? - person Alex; 13.02.2014
comment
@ Алекс, да, другой может дать тебе false, если ты проверяешь массив, полученный от <iframe>. - person gdoron is supporting Monica; 13.02.2014
comment
@gdoron MDN, кажется, указывает, что Array.isArray(…) должен быть надежным developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/? - person Mark Fox; 26.07.2015
comment
@m, вы правы, но не поддерживается в старых браузерах. см. здесь - person gdoron is supporting Monica; 26.07.2015
comment
Вы можете определить, есть ли у вас массив или объект, используя этот способ: if(typeof myArrayOfObject[0] == "object"). Если true, то у вас есть объект, если false, то у вас есть массив. - person Jan Chalupa; 08.12.2015
comment
Я получил ["1"] instanceof Object как true. Надежна ли проверка с помощью data instanceof Array? - person Romesh; 04.09.2020

Цитирование спецификации

15.4 Объекты массива

Объекты-массивы придают особое значение определенному классу имен свойств. Имя свойства P (в виде строкового значения) является индексом массива тогда и только тогда, когда ToString(ToUint32(P)) равно P, а ToUint32(P) не равно 2^32-1. Свойство, имя свойства которого является индексом массива, также называется элементом. Каждый объект Array имеет свойство длины, значение которого всегда является неотрицательным целым числом, меньшим 2^32. Значение свойства length численно больше, чем имя каждого свойства, имя которого является индексом массива; всякий раз, когда свойство объекта Array создается или изменяется, другие свойства настраиваются по мере необходимости, чтобы сохранить этот инвариант. В частности, всякий раз, когда добавляется свойство, имя которого является индексом массива, свойство длины при необходимости изменяется, чтобы быть на единицу больше, чем числовое значение этого индекса массива; и всякий раз, когда изменяется свойство длины, каждое свойство, имя которого является индексом массива, значение которого не меньше новой длины, автоматически удаляется. Это ограничение применяется только к собственным свойствам объекта Array и не зависит от свойств длины или индекса массива, которые могут быть унаследованы от его прототипов.

А вот таблица для typeof

введите здесь описание изображения


Чтобы добавить немного фона, в JavaScript есть два типа данных:

  1. Примитивные типы данных. Сюда входят null, undefined, string, boolean, number и object.
  2. Производные типы данных/специальные объекты. К ним относятся функции, массивы и регулярные выражения. И да, все они получены из «Объекта» в JavaScript.

Объект в JavaScript похож по структуре на ассоциативный массив/словарь, встречающийся в большинстве объектно-ориентированных языков, т. е. он имеет набор пар ключ-значение.

Массив можно рассматривать как объект со следующими свойствами/ключами:

  1. Длина. Может быть 0 или выше (неотрицательное значение).
  2. Индексы массива. Под этим я подразумеваю, что «0», «1», «2» и т. д. — все это свойства объекта массива.

Надеюсь, это помогло пролить больше света на то, почему typeof Array возвращает объект. Ваше здоровье!

person Prinzhorn    schedule 21.10.2012
comment
объект не является примитивным в соответствии с: developer.mozilla.org/en-US/docs /Глоссарий/Примитивы - person Potatoes; 27.07.2017

Попробуйте этот пример, и вы также поймете, в чем разница между ассоциативным массивом и объектом в 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 возвращает объект... может возвращать ассоциативный массив... но это не так

person Reflective    schedule 21.10.2012
comment
JSON также имеет концепцию массивов. (И индексы массива начинаются с 0.) - person pimvdb; 21.10.2012
comment
Парень определил свои данные как { ... } - Объект ... Я пытаюсь объяснить ему, в чем разница между ч / б ассоциативным массивом и объектами. На самом деле он проверяет дату, возвращаемую сервером, так что это не то же самое... но, может быть, вы правы... надо проверить :) - person Reflective; 21.10.2012
comment
Можете ли вы привести пример ассоциативного массива JSON? Что-то вроде этого: jQuery.parseJSON('{"name":"John"}') ... Этот обычно принимается за Объект. Как вы думаете, как JSON представляет ассоциативный массив? - person Reflective; 21.10.2012
comment
В JSON нет того, что вы называете ассоциативным массивом. Но я не уверен, что вы пытаетесь сказать своим ответом на вопрос. - person pimvdb; 21.10.2012
comment
При всем моем уважении, в JavaScript есть такая штука, как Ассоциативный массив... проверьте... это то, что я пытался объяснить... и какое почтение, когда вы вызываете isArray. Ассоциативный массив — это HASH в Perl, например, или обычно называемый словарем. JSON не имеет такого представления... поэтому ассоциативный массив рассматривается как объект со свойствами. - person Reflective; 21.10.2012
comment
Но как это отвечает на вопрос? У OP есть массив, и typeof дает "object". Ему интересно, почему это происходит. Короче вопрос: почему typeof [] не дает "array"? Вы толком не ответили на этот вопрос. - person pimvdb; 21.10.2012
comment
Отвечает на половину вопросов о том, что JSON возвращает объект, а не массив, и дает некоторую дополнительную информацию о том, что из-за синтаксиса JSON всегда анализирует массивы как объекты, а не как ассоциативный массив, что можно сделать, потому что ассоциативный массив существует как тип, но к сожалению, JSON так не работает и не возвращает ассоциативный массив. Ассоциативный массив имеет некоторые недостатки, и хорошо использовать объекты. Например, получить длину, которую я объяснил в своем ответе. Итак, идея состоит в том, чтобы понять, почему они используют Objects для разбора строки JSON. Хоть чему-то научился. Правильно? - person Reflective; 21.10.2012
comment
Здесь нет ничего плохого в JSON; data на самом деле является массивом. OP вообще не использует ассоциативные массивы. Вопрос в том, почему typeof дает "object" при использовании в массиве. Но я предполагаю, что мы говорим на разных волнах. - person pimvdb; 21.10.2012
comment
{ key: value } определяет объект, а не массив. Как вы знаете, чтобы определить массив, вы должны сделать ['mick__romney']. Другое дело, что data, который проверяет парень, является результатом парсера запроса AJAX и не имеет ничего общего с параметром data: в настройках AJAX. Ответ заключается в том, что JSON переводит все массивы, передаваемые строками JSON, в объекты. Не может быть разным, не имеет значения, выглядят ли они как массив. Многие способы решения проблемы, например. try { var a = data.scrren_name; isArray = true; } catch (e) { isArray = false;} ... но лучше немного углубиться в проблему. - person Reflective; 21.10.2012
comment
в любом случае... бесполезно говорить об этом :) давайте настроимся на канал "самых свежих вопросов" ;) - person Reflective; 21.10.2012
comment
JSON определенно не переводит все массивы, передаваемые строками JSON, в объекты. При анализе такие массивы с использованием квадратных скобок становятся фактическими массивами JS, а не объектами. Кроме того, в первом примере в вашем ответе a.length не будет неопределенным, это будет 3. - person nnnnnn; 21.10.2012
comment
Насчет .length - надо сначала попробовать (как показано в примере выше)... will be не означает it is... и понятно объяснено почему. О массивах: я говорил об ассоциативных массивах, может быть, это неясно, потому что я написал 100 строк и, возможно, я пропустил это уточнение. Но скажите, пожалуйста, как в JSON представляется ассоциативный массив? Ответив себе на этот вопрос, вы, наконец, прекратите эту бесконечную дискуссию. И когда вы обнаружите, что .length не работает для ассоциативного массива, будьте так смелы, чтобы сказать - хорошо, моя ошибка - person Reflective; 21.10.2012
comment
Представление массива в формате JSON: "[1,2,3]" — при разборе будет создан массив [1,2,3], который имеет .length из 3 и для которого Array.isArray() вернет true. То есть Array.isArray(JSON.parse("[1,2,3]")) равно true (попробуйте). То, что вы называете ассоциативным массивом в своем ответе, представляет собой стандартный массив JS с добавленными дополнительными нечисловыми свойствами, который не может быть представлен в JSON (кроме объекта, не являющегося массивом, который вам нужно преобразовать в массив) . - person nnnnnn; 22.10.2012
comment
P.S. В вашем примере a.length будет 3 - ты попробуй, тут ты ошибаешься. Свойство length будет на единицу выше, чем свойство с наивысшим числовым индексом в массиве, т. е. оно игнорирует любые дополнительные нечисловые свойства, которые вы добавляете, такие как ваш пример a['key'], но length не будет неопределенным - возможно, это то, что вы пытались сказать. Ассоциативный массив существует и в других языках, но в JavaScript наиболее близким является простой объект. - person nnnnnn; 22.10.2012
comment
Наверное, это зависит от браузера моего мастера, но в любом случае это не правильная длина ... Если у вас есть только ключи, это будет 0, но я рад, что вы наконец поняли, о чем я говорю. Я не говорю о массиве [1,2,3], который является абсолютно обычным массивом. Внимательно прочитайте. Добавление ключа 'key' делает его ассоциативным (HASH, Dictionary). Не я даю имена, это так называется. В последний раз: есть разные ч/б ассоц. массив и объект - isArray вернет true для ассоциированного объекта. массив и false для объекта. Google: ассоциативный массив JavaScript - person Reflective; 22.10.2012
comment
Читая ваши ответы, я думаю, что вы никогда не слышали об ассоциативных массивах и не верите в их существование :) В любом случае, такая дискуссия бесполезна. Не буду тратить время на споры о вещах, которые можно легко проверить. - person Reflective; 22.10.2012