Являются ли массивы Javascript примитивами? Строки? Объекты?

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

Я всегда думал, что массивы и объекты в JS по сути одинаковы, в первую очередь потому, что доступ к ним идентичен.

var obj = {'I': 'me'};
var arr = new Array();
arr['you'] = 'them';

console.log(obj.I);
console.log(arr.you);
console.log(obj['I']);
console.log(arr['you']);

Я ввел в заблуждение / ошибся / ошибся? Что мне нужно знать о литералах JS, примитивах и строках / объектах / массивах / и т.д...?

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

7 ответов

Решение

Массивы являются объектами.

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

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

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

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

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

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

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

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

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

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

var str = 'yes';

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

var str = new String('yes');

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


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

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

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

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

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

Попробуй это

var a = Array;

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

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

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

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

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

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

myObj.attribute или myObj["атрибут"]

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

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

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

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

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

  • длина
  • От себя
  • поп

Объект объявлен как 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 как объект, но не обязательно будет доступен для зацикливания, как выделено выше.

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

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

Другие вопросы по тегам