Являются ли 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, примитивах и строках/объектах/массивах/etc...?
Являются ли массивы/объекты просто строками в маскировке? Почему, почему нет? Каким образом (они) они (такие/нет)?
Ответы
Ответ 1
Массивы - это объекты.
Однако, в отличие от обычных объектов, массивы имеют определенные особенности.
-
Массивы имеют дополнительный объект в цепочке прототипов, а именно Array.prototype
. Этот объект содержит так называемые методы массива, которые можно вызвать в экземплярах массива. (Список методов находится здесь: http://es5.github.com/#x15.4.4)
-
Массивы имеют свойство length
(которое является живым, ergo, оно автоматически обновляется) (читайте здесь: http://es5.github.com/#x15.4.5.2)
-
Массивы имеют специальный алгоритм определения новых свойств (читайте здесь: http://es5.github.com/#x15.4.5.1). Если вы установите новое свойство в массив, и это имя свойства является sting, которое может быть принудительно применено к целочисленному числу (например, '1'
, '2'
, '3'
и т.д.), Тогда применяется специальный алгоритм (он определен на стр. 123 в спецификации)
Помимо этих трех вещей, массивы похожи на обычные объекты.
Читайте о массивах в спецификации: http://es5.github.com/#x15.4
Ответ 2
Объекты представляют собой неупорядоченную карту из строковых ключей в значения, массивы представляют собой упорядоченный список значений (с целыми ключами). Это главное отличие. Они оба не примитивны, поскольку они состоят из нескольких значений, что также подразумевает передачу по ссылке в JavaScript.
Массивы также являются своего рода объектом, поэтому вы можете присоединить к ним дополнительные свойства, получить доступ к их прототипу и т.д.
В вашем пересмотренном примере вы используете только тот факт, что массив является фактически объектом, т.е. вы можете установить для них какое-либо свойство. Вы не должны этого делать. Если вам не нужен упорядоченный список значений, используйте простой объект.
Ответ 3
Строки могут быть либо примитивными, либо объектами, в зависимости от того, как они были объявлены.
var str = 'yes';
Дает вам примитив, а
var str = new String('yes');
предоставит вам объект String.
Все массивы одинаковы (независимо от того, были ли они определены с помощью [] или нового массива()), относятся к типу объекта и наследуются от прототипа объекта "Массив". В Javascript нет реальных классов, все это объект, и есть системный объект, называемый Array. Он имеет свойство, называемое 'prototype' (объекта типа), и когда вы используете новое ключевое слово для объекта с свойством prototype, он создает экземпляр со ссылкой на содержимое прототипа и сохраняет его в вашей переменной. Таким образом, все массивы, которые вы когда-либо использовали в Javascript, являются объектами и экземплярами свойства прототипа Array.
В любом случае, хотя массивы действительно являются объектами, они ведут себя как массивы из-за их полезных свойств и функций (таких как длина, срез, толчок и т.д.).
Еще одно замечание, хотя я сказал, что нет классов, когда вы это делаете:
console.log(Object.prototype.toString.call(your_object));
он даст вам строку в форме [object Object]. Но полезно то, что когда вы вызываете его с помощью массива, вы получаете [object Array] то же самое с функциями, которые дают [object Function] и ряд других системных типов, которые помогают дифференцировать обычные объекты и массивы (так как typeof оператор всегда просто возвращает строку "объект" ).
Попробуйте это
var a = Array;
и зайдите в firebug и изучите содержимое a, особенно это свойство 'prototype'.
Изменить: Немного изменил формулировку, чтобы быть более правильным. Фактически, когда вы используете новое ключевое слово, он создает экземпляр, который ссылается на объект прототипа. Таким образом, любые изменения, внесенные в прототип после объявления экземпляра, будут по-прежнему влиять на экземпляр.
Изменить: В ответ на ваш последний пересмотренный вопрос (массивы/объекты фактически замаскированы строками): Нет. Это объекты, как я объяснил. Строки являются либо примитивным типом, либо типом объекта (экземпляр объекта String), который содержит примитивный эквивалент в качестве одного из его свойств.
Ответ 4
Массивы не являются примитивами в Javascript, они являются объектами. Главное различие заключается в том, что в результате, когда вы передаете массив функции, он передается по ссылке, а не по значению.
Так что да! Массивы - это объекты в javascript, с полномасштабным Array.prototype и всем (не трогайте это, хотя...)
Путаница возникает из-за того, что javascripts позволяет вам получить доступ к атрибутам объекта двумя способами:
myObj.attribute
или
myObj [ "атрибут" ]
Действительно, что делает массив массивом не имеет ничего общего с тем, как вы храните данные - любой объект может хранить значения с использованием синтаксиса, который вы используете для хранения массива, - что делает массив массивом фактом, что методы массива (например, shift() и sort()) определены для Array.prototype.
Ответ 5
Попытка быть кратким из того, что, по моему мнению, имеет наибольшее значение: в массивах есть несколько методов, которые нет у объектов. В том числе:
Объект, объявленный как 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
как объект, но не обязательно будет доступен, как показано выше.
Не то, что я говорю, что вы не можете перебирать свойства объекта, просто при работе с Array вы используете эту уникальную функциональность и не должны недоумевать.
Ответ 6
В JavaScript у вас есть несколько типов, все остальное - это объект. Типы в JavaScript: boolean, number и string. Существуют также два специальных значения: "null" и "undefined".
Итак, квест "это массив JavaScript?"? немного неоднозначна. Да, массив JavaScript - это "объект", но это не экземпляр "Объект". Массив JavaScript - это экземпляр "Массив". Хотя все объекты наследуются от Object; вы можете просмотреть цепочку наследования MDC. Кроме того, массивы имеют несколько иные свойства, чем объект. Массивы имеют свойство .length
. Они также имеют методы .slice()
, .join()
и т.д.
Douglas Crockford предоставляет приятный survey особенности языка. В его обзоре обсуждаются различия, о которых вы спрашиваете. Кроме того, вы можете узнать больше о разнице между литералами и конструкторами в вопросе # 4559207.
Ответ 7
Массивы являются объектами, но имеют особый характер. Объекты представляют собой коллекции значений, индексированных ключами (в нотации Javascript, {'key': 'value'}
), тогда как массивы - это объекты, ключи которых являются числовыми (с несколькими функциями и свойствами). Основное различие между ними очевидно, когда вы используете цикл for each
- объект будет перебирать все значения в своих свойствах, тогда как Array вернет ключи вместо этого. Вот ссылка на JSFiddle, демонстрирующую разницу, - обратите внимание, что первый for each
, который использует массив, возвращает индексы, а не значения; напротив, второй for each
возвращает фактические значения на этих клавишах.