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

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

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

и

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

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

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

Ответы [ 7 ]

129 голосов
/ 17 мая 2009

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

Вот более конкретный пример того, почему нецифровые ключи не «соответствуют» массиву:

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

alert(myArray.length);

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

14 голосов
/ 17 мая 2009

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

Функции, такие как:

concat
every   
filer
forEach
join
indexOf
lastIndexOf
map
pop
push
reverse
shift
slice
some
sort
splice
toSource
toString
unshift
valueOf 
6 голосов
/ 18 мая 2011

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

Экземпляр 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 объектно-ориентированный стиль программирования (ООП - объектно-ориентированный стиль программирования - "s" - мой собственный каламбур!) Был в моде, и интерпретатор был аналогично крещен с Java, чтобы дать это большее доверие. Методы функционального программирования были отнесены к более абстрактным и эзотерическим экзаменам с изучением теорий автоматов, рекурсивных функций, формальных языков и т. Д. И, как таковые, не столь приемлемы. Тем не менее, сильные стороны этих формальных соображений ясно проявляются в Javascript, в частности, как это реализовано в движке Gecko FF (то есть. .toSource()).


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

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

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

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

5 голосов
/ 17 мая 2009

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

код

var myArray = Array();

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

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

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

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

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

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

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

1 голос
/ 19 апреля 2018

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

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

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

1 голос
/ 23 января 2017

Одно практическое отличие заключается в использовании 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"}
0 голосов
/ 17 мая 2009

Примечание {} - это просто синтаксический сахар, делающий код приятнее; -)

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

var Func = new Function("<params>", "<code>");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...