Почему я могу добавить именованные свойства в массив, как если бы это был объект?

Следующие два разных фрагмента кода кажутся мне похожими:

var myArray = Array();
myArray['A'] = "Athens";
myArray['B'] = "Berlin";

и

var myObject = {'A': 'Athens', 'B':'Berlin'};

потому что они оба ведут себя одинаково, а также typeof(myArray) == typeof(myObjects) (оба дают "объект" ).

Есть ли разница между этими вариантами?

Ответ 1

Практически все в javascript является объектом, поэтому вы можете "злоупотреблять" объектом Array, устанавливая на нем произвольные свойства. Этот должен считаться вредным. Массивы для индексированных по цифре данных - для нечисловых ключей используют объект.

Вот более конкретный пример, почему нечисловые клавиши не "подходят" к массиву:

var myArray = Array();
myArray['A'] = "Athens";
myArray['B'] = "Berlin";

alert(myArray.length);

Это не отображает "2", но "0" - эффективно, никакие элементы не добавлены в массив, а некоторые новые свойства добавлены в объект массива.

Ответ 2

В массивах JS есть объекты, слегка модифицированные (с несколькими функциями).

Функции вроде:

concat
every   
filer
forEach
join
indexOf
lastIndexOf
map
pop
push
reverse
shift
slice
some
sort
splice
toSource
toString
unshift
valueOf 

Ответ 3

Все в JavaScript является объектом, кроме примитивных типов.

Код

var myArray = Array();

создает экземпляр объекта Array, а

var myObject = {'A': 'Athens', 'B':'Berlin'};

создает экземпляр объекта Object.

Попробуйте использовать следующий код

alert(myArray.constructor)
alert(myObject.constructor)

Итак, вы увидите, что разница в типе конструктора объекта.

Экземпляр объекта Array будет содержать все свойства и методы прототипа Array.

Ответ 4

Я думаю, что я слишком метафоричен и загадочен с предыдущим ответом. Далее следует разъяснение.

Экземпляр Array, Boolean, Date, Function, Number, RegExp, String является объектом, но расширен с методами и свойствами, специфичными для каждого типа. Например, массив имеет предопределенное свойство length, а общие объекты - нет.

javascript:alert([].length+'\n'+{}.length)

отображает

0
undefined

По сути, интерпретатор FF Gecko также различает массивы и общие объекты с различными различиями, оценивающими языковые конструкции.

javascript:
  ra=[  "one",   "two",   "three"]; ra.a=4;
  ob={0:"one", 1:"two", 2:"three"}; ob.a=4;
  alert(
    ra            +"\n\n"+
    ob            +"\n\n"+
    ra.toSource() +"\n\n"+
    ra.a          +"\t .toSource() forgot me! \n\n"+
    ra.length     +"\t and my length! \n\n"+
    ob.toSource());
  ps=""; for(i in ra)ps+=i+" "; alert(ps);  /* NB .length is missing! */
  ps=""; for(i in ob)ps+=i+" "; alert(ps);

отображения

one,two,three

[object Object]

["one", "two", "three"]

4    .toSource() forgot me! 

3    and my length! 

({0:"one", 1:"two", 2:"three", a:4})

и 0 1 2 a и 0 1 2 a.

Относительно утверждения, что все объекты являются функциями:

Синтаксически или семантически корректно использовать экземпляр любого объекта как функцию, например 123() или "abc"() или []() или {}() или obj(), где obj - это любой тип, отличный от Function, поэтому произвольный объект INSTANCE не является Function. Однако, учитывая объект obj и он набирается как Array, Boolean, Date, ..., как obj стал Array, Boolean, Date, ...? Что такое Array, Boolean, Date, ...?

javascript:
    alert([Array, Boolean, Date, Function, 
              Number, Object, RegExp, String] . join('\n\n') );

отображает

function Array() {
    [native code]
}

function Boolean() {
    [native code]
}

function Date() {
    [native code]
}

function Function() {
    [native code]
}

function Number() {
    [native code]
}

function Object() {
    [native code]
}

function RegExp() {
    [native code]
}

function String() {
    [native code]
}

В любом случае, без двусмысленности, тип объекта проявляется как определение Function, поэтому утверждение о том, что все объекты являются функциями! (Язык в щеке заключается в том, что я намеренно скрыл и размыл различие экземпляра объекта с его типом! Тем не менее, это показывает, что "вы не можете иметь один без другого", объект и функция! Капитализация подчеркивает тип как против экземпляра.)

Как функциональная, так и объектная парадигма, по-видимому, имеют фундаментальное значение для программирования и реализации встроенных примитивов низкого уровня интерпретатора JS, таких как Math и JSON и true.

 javascript:alert([Math, JSON, true.toSource()].join("\n\n"));

отображает

[object Math]

[object JSON]

(new Boolean(true))

Во время разработки Javascript объектно-ориентированный стиль программирования (OOP - Object Oriented Programming style - "s" - это мой собственный каламбур!) был в моде, и интерпретатор был так же окрещен с Java, чтобы дать это большая вероятность. Методы функционального программирования были отнесены к более абстрактным и эзотерическим экзаменам, изучающим теории автоматов, рекурсивных функций, формальных языков и т.д. И, как таковые, не приемлемые. Однако сильные стороны этих формальных соображений явно проявляются в Javascript, особенно в исполнении FF Gecko engine (т.е. .toSource()).


Определение объекта для функции особенно удовлетворительно, поскольку оно определяется как рекуррентное соотношение! определяемый с помощью его собственного определения!

function Function() { [native code] }
и поскольку функция является объектом, то те же чувства сохраняются для function Object() { [native code] }.

Большинство других определений задают статическое конечное значение. Однако eval() является особенно мощным примитивом, поэтому String также может вставлять произвольную функциональность.

Обратите внимание, что используемый выше язык не скрывает тип объекта и различие между экземплярами.

Ответ 5

Одно практическое отличие заключается в том, что при использовании JSON.stringify в array все нечисловые индексы игнорируются:

var arr = [];
var obj = {};

arr['name'] = 'John';
obj['name'] = 'John';

console.log(arr);    // will output [name: "John"]
console.log(obj);    // will output {name: "John"}

JSON.stringify(arr); // will return []
JSON.stringify(obj); // will return {"name":"John"}

Ответ 6

Разница между массивами и другими объектами в JavaScript. Хотя массивы имеют волшебное обновление свойства length, для объектов, отличных от массивов, нет способа реализовать такое свойство.

var arrName = [];
arrName[5] = "test";
arrName.length; // <- 6

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

Ответ 7

{} -нотация - это просто синтаксический сахар, чтобы сделать код более приятным; -)

В JavaScript есть много подобных конструкций, таких как построение функций, где функция() является просто синонимом

var Func = new Function("<params>", "<code>");