Javascript Array Object vs Array Like Objects - Уточнение - PullRequest
6 голосов
/ 08 февраля 2012

Я пытался структурировать массивоподобный объект, который был объявлен как объект массива, и обнаружил, что JSON.stringify неправильно обрабатывает массивоподобный объект, когда он определен как объект массива.

См. Ниже для большей ясности: -> jsFiddle

var simpleArray = []; //note that it is defined as Array Object 

alert(typeof simpleArray); // returns object -> Array Object

simpleArray ['test1'] = 'test 1';
simpleArray ['test2'] = 'test 2';

alert(JSON.stringify(simpleArray)); //returns [] 

Он работал нормально и возвращал мне {"test1":"test 1","test2":"test 2"}, когда я изменил

var simpleArray = []; на var simpleArray = {};,

Может кто-нибудь пролить свет или ссылку, где я могу прочитать больше?

Редактировать:

Вопрос: Когда typeof simpleArray = [] и simpleArray = {} возвращали объект, почему JSON.stringify не смог вернуть {"test1":"test 1","test2":"test 2"} в обоих случаях

Ответы [ 7 ]

4 голосов
/ 08 февраля 2012

Разница в показателях. Когда вы используете массив [], индексы могут быть только положительными целыми числами.

Итак, следующее неверно:

var array = [ ];
array['test1'] = 'test 1';
array['test2'] = 'test 2';

потому что test1 и test2 не являются целыми числами. Чтобы это исправить, вам нужно использовать целочисленные индексы:

var array = [ ];
array[0] = 'test 1';
array[1] = 'test 2';

или если вы объявляете объект javascript, тогда свойства могут быть любыми строками:

var array = { };
array['test1'] = 'test 1';
array['test2'] = 'test 2';

что эквивалентно:

var array = { };
array.test1 = 'test 1';
array.test2 = 'test 2';
2 голосов
/ 08 февраля 2012

«Может кто-нибудь пролить свет или какую-нибудь ссылку, где я могу прочитать больше?»

Когда вы имеете дело с JSON данными, вы можете обратиться к json.org , чтобы прочитать о требованиях спецификации.

В JSON Array - это список порядка значений, разделенных ,.

enter image description here

Таким образом, JSON.stringify() просто игнорирует все, что не может быть представлено в виде простого упорядоченного списка.

Так что, если вы делаете ...

var simpleArray = [];
simpleArray.foo = 'bar';

... вы все еще задаете массив, поэтому он ожидает только числовые индексы и игнорирует все остальное.

Поскольку JSON не зависит от языка, методы работы с JSON должны принять решение о том, какая языковая структура лучше всего подходит для каждой JSON структуры.

Итак, JSON имеет следующие структуры ...

{} // object
[] // array

Вы должны заметить, что, хотя выглядят очень похожи на JavaScript объекты и массивы, они не строго совпадают.

Любые JavaScript структуры, используемые для создания JSON структур, должны соответствовать тому, что позволят JSON структуры. Вот почему нечисловые свойства удалены исключены.

Пока JavaScript не против, JSON не потерпит их.

2 голосов
/ 08 февраля 2012

Вам не нужен массив. Когда вам нужен «ассоциативный массив» в JavaScript, вам действительно нужен объект, {}.

Вы можете различить их с instanceof Array:

[] instanceof Array // true
({}) instanceof Array // false

РЕДАКТИРОВАТЬ: может обрабатывать. Он сериализует все элементы массива. Однако, чтобы быть элементом, должен быть цифровой ключ. В этом случае их нет.

В этом нет ничего уникального для JSON. Это соответствует toSource и свойству length.

1 голос
/ 08 февраля 2012

Различия между экземплярами Array и другими объектами указаны в Спецификации языка ECMAScript, издание 5.1 , раздел 15.4.

Там вы обнаружите, что в то время как вы можете использовать синтаксис метода доступа к скобкам со всеми ссылками на объекты -

objRef[propertyName]

- Array экземпляры особенные. Только при использовании значения параметра, строковое представление которого представляет собой 32-разрядное целое число без знака меньше 2 32 -1, осуществляется доступ к элементу структуры инкапсулированного массива, а доступ на запись влияет на значение Array свойство length экземпляра.

В разделе 15.12 соответственно указывается объект JSON и его метод stringify.

1 голос
/ 08 февраля 2012

Когда JSON.stringify встречает массив, он выполняет итерацию аналогично циклу for от 0 до simpleArray.length, чтобы найти значения.Например:

var a = [];
a[5] = "abc";
alert(JSON.stringify(a)); // alerts [null,null,null,null,null,"abc"]

Поэтому установка свойств для него будет полностью невидима для JSON.

Однако определение объекта с помощью {} заставляет JSON рассматривать его как объект и, следовательно, оно зацикливаетсяповерх свойств объекта (исключая унаследованные свойства из цепочки прототипов).Таким образом он может найти ваши свойства test1 и test2 и успешно вернуть то, что вы ожидаете.

0 голосов
/ 08 февраля 2012

В Javascript все является объектом, так что даже Массивы. Вот почему вы получаете:

>> var l = [1, 2];
>> typeof l
"object"

Массивы хранятся так же, как объекты. Таким образом, по сути, массивы являются только объектами хеш-таблицы. Индекс, который вы указываете при доступе, например,

>> l[0]

не интерпретируется как смещение, но хэшируется и затем ищется.

Итак, массивы - это просто объекты (с некоторыми встроенными методами-массивами), и поэтому вы можете обращаться с ними как с объектами и помещать значение под определенным ключом. Но только те ключи, которые проиндексированы цифрами, используются для вычисления длины.

>> var l = []
>> l.length
0
>> l[5] = 1;
>> l.length
6
>> l
[undefined, undefined, undefined, undefined, undefined, 1]
>> l.hello = "Hello"
>> l.length
6

Читать Массив - MDN для получения дополнительной информации и Ассоциативные массивы считаются вредными , почему вы не должны этого делать.

0 голосов
/ 08 февраля 2012

Ваш код не является семантически правильным, но поскольку большинство движков JavaScript действительно хороши для программиста, они допускают следующие типы ошибок .

Быстрый тестовый пример:

var a = [];
a.b = "c";
console.log(JSON.stringify(a));//yields [], and not {"b":"c"} as you might expect

Это может быть связано с некоторой строгостью в JSON.stringify, которая по-прежнему трактует a как Array.Я бы не стал сильно беспокоиться об этом.Это ситуация, которая не должна возникать в вашей программе, потому что это ошибка. JSLint - популярный инструмент для выявления этих и многих других потенциальных проблем в вашем коде.

...