Являются ли массивы Javascript примитивами?Строки?Объекты? - PullRequest
20 голосов
/ 19 февраля 2011

Являются ли массивы просто замаскированными объектами?Почему, почему нет?Каким образом они (такие / нет)?

Я всегда считал массивы и объекты в JS по сути одинаковыми, главным образом потому, что доступ к ним идентичен.* Я ввел в заблуждение / ошибся / ошибся?Что мне нужно знать о литералах JS, примитивах и строках / объектах / массивах / и т. Д.?Почему, почему нет?Каким образом они (такие / нет)?

Ответы [ 7 ]

34 голосов
/ 19 февраля 2011

Массивы - это объекты.

Однако, в отличие от обычных объектов, у массивов есть определенные особенности.

  1. Массивы имеют дополнительный объект в своей цепочке прототипов, а именно Array.prototype.Этот объект содержит так называемые методы Array, которые можно вызывать для экземпляров массива.(Список методов приведен здесь: http://es5.github.com/#x15.4.4)

  2. Массивы имеют свойство length (которое является активным, то есть автоматически обновляется) (Читать здесь: http://es5.github.com/#x15.4.5.2)

  3. Массивы имеют специальный алгоритм определения новых свойств (читайте здесь: http://es5.github.com/#x15.4.5.1). Если вы задаете новое свойство для массива, и имя этого свойства является строкой, которую можно привести к целому числу (например, '1', '2', '3' и т. Д.), Затем применяется специальный алгоритм (он определен на стр. 123 в спецификации)

Кроме этих трех вещей, массивыкак обычные объекты.

Читайте о массивах в спецификации: http://es5.github.com/#x15.4

8 голосов
/ 19 февраля 2011

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

Массивы также являются своего рода объектом, поэтому вы можете присоединять дополнительные свойстваим доступ к их прототипу и т. д.

В вашем пересмотренном примере вы используете только тот факт, что массив на самом деле является объектом, то есть вы можете установить любое свойство для них.Ты не должен этого делать.Если вам не нужен упорядоченный список значений, используйте простой объект.

6 голосов
/ 19 февраля 2011

Строки могут быть либо примитивами, либо объектами, в зависимости от того, как они были объявлены.

var str = 'yes';

Дает вам примитив, а

var str = new String('yes');

даст вам объект String.


Все массивы одинаковы (независимо от того, были они определены с помощью [] или new Array ()), относятся к типу объекта и наследуются от прототипа объекта "Array".В Javascript нет реальных классов, все является объектом, и существует системный объект, называемый Array.У него есть свойство с именем «prototype» (типа object), и когда вы используете ключевое слово new для объекта со свойством prototype, оно создает экземпляр со ссылкой на содержимое прототипа и сохраняет его в вашей переменной.Таким образом, все массивы, которые вы когда-либо использовали в Javascript, являются объектами и экземплярами свойства прототипа массива.

В любом случае, хотя массивы действительно являются объектами, они ведут себя как массивы из-за своих полезных свойств и функций (таких как длина, slice, push и т. д.).

Еще одно замечание, хотя я и сказал, что когда вы сделаете это, классов не будет:

console.log(Object.prototype.toString.call(your_object));

он выдаст вам строку в форме [object Object].Но что полезно, так это то, что когда вы вызываете его с массивом, вы получаете [object Array] то же самое с функциями, которые предоставляют [object Function] и ряд других типов, определенных системой, что помогает различать обычные объекты и массивы (так как typeofоператор всегда будет просто возвращать строку 'object').

Попробуйте это

var a = Array;

и зайдите в firebug и изучите содержимое a, особенно его свойства 'prototype'.

Редактировать: Немного изменили формулировку, чтобы быть более корректной.Фактически, когда вы используете ключевое слово new, он создает экземпляр, который ссылается на объект-прототип.Таким образом, любые изменения, внесенные в прототип после объявления экземпляра, все равно будут влиять на экземпляр.

Редактировать: В ответ на ваш последний исправленный вопрос (действительно ли массивы / объекты являются замаскированными строками):Нет. Это объекты, как я объяснил.Строки являются либо примитивным типом, либо типом объекта (экземпляр объекта String), который содержит примитивный эквивалент в качестве одного из своих свойств.

3 голосов
/ 19 февраля 2011

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

Так что да!Массивы - это объекты в javascript, с полноценным Array.prototype и всем остальным (не трогайте это, хотя ...)

Путаница связана с тем, что javascripts позволяет получить доступ к атрибутам объекта двумя способами:1005 *

myObj.attribute или myObj ["attribute"]

Реально то, что делает массив массивом, не имеет ничего общего с тем, как вы храните данные - любой объект может хранить значения, используя используемый вами синтаксисхранить массив - что делает массив массивом, так это то, что методы массива (например, shift () и sort ()) определены для Array.prototype.

1 голос
/ 19 февраля 2011

В JavaScript у вас есть несколько типов, все остальное является объектом.Типы в JavaScript: логическое, число и строка.Есть также два специальных значения: «null» и «undefined».

Итак, квест «Является ли массив JavaScript объектом?»немного двусмысленно.Да, массив JavaScript - это «объект», но он не является экземпляром «объекта».Массив JavaScript является экземпляром массива.Хотя все объекты наследуются от Object;Вы можете просмотреть цепочку наследования на MDC .Кроме того, массивы имеют немного отличающиеся свойства, чем объект.Массивы имеют свойство .length.У них также есть методы .slice(), .join() и т. Д.

Дуглас Крокфорд предлагает хороший обзор возможностей языка.Его опрос обсуждает различия, о которых вы спрашиваете.Кроме того, вы можете прочитать больше о разнице между литералами и конструкторами в вопросе # 4559207.

1 голос
/ 19 февраля 2011

Попытка быть краткой с тем, что я считаю наиболее значимым: у массивов есть ряд методов, которых нет у объектов.Включая:

  • длина
  • push
  • pop

Объект, объявленный как var x = {foo:bar}, не имеет доступа к .length () метод.Они оба являются объектами, но с массивом как своего рода надмножеством с методами, упомянутыми выше.

Я не чувствую, что это даже близко к стандарту Крокфорда с точки зрения объяснения, но я пытаюсьБудьте краткими.

Если вы хотите получить быстрые результаты, откройте Firebug или консоль javascript и попробуйте Array.prototype и Object.prototype, чтобы увидеть некоторые детали

Обновление: В вашем примере вы объявляете массив, а затем делаете:

foo['bar'] = 'unexpectedbehaviour';

даст неожиданные результаты и не будет доступен в простых циклах, таких как:

var foo=[0,1];
foo['bar'] = 2;

for(var i=0;i<foo.length;i++){
    console.log(foo[i]);
}

//outputs: 
//0
//1

Массив можетпринять foo['bar']=x или foo.bar=y как объект, но не обязательно будет доступен для зацикливания, как выделено выше.

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

0 голосов
/ 19 февраля 2011

Массивы - это Объекты, но специализированного характера. Объекты - это наборы значений, проиндексированных ключами (в нотации Javascript, {'key': 'value'}), тогда как массивы - это объекты, ключи которых являются числовыми (с несколькими функциями и свойствами). Разница между ними очевидна, когда вы используете цикл for each - объект будет перебирать все значения в своих свойствах, тогда как массив будет возвращать ключи вместо этого. Вот ссылка на JSFiddle, демонстрирующая разницу - обратите внимание, что первый for each, использующий массив, возвращает индексы, а не значения; напротив, вторая for each возвращает действительные значения по этим клавишам.

...