JavaScript: массивы vs объекты

При изучении JavaScript объектов, все мы натыкаемся на фразы типа “Массивы – это простые объекты в Javascript”. Сегодня я хочу глубже изучить это утверждение:

Посмотреть пример

Если посмотреть на пример, приведенный выше, то становится очевидно, что массив - это тип объекта. Но что это значит?

Если вы не знакомы с оператором typeof, то подробнее узнать о нем можно здесь.

Наследование

Чтобы понять разницу между JavaScript работой с объектами и массивами, рассмотрим принцип наследования.

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

Посмотреть пример

В примере выше создается объект person с собственным параметром name. При вызове метода toString сначала проверяется объект person, за которым следует проверка его прототипа (Object.prototype). Используется логика прототипа, которая обычно возвращает [object Object].

Далее, в самом объекте person создайте метод toString, который мы и будем использовать при запуске toString.

Разница между объектами и массивами

У массивов есть существенные отличия от традиционных JavaScript объектов. Причина кроется в объекте Array.prototype, в котором представлены все методы, присущие массивам. Каждый новый массив наследует эти методы из Array.prototype.

Важно отметить, что значением свойства prototype в Array.prototype является Object.prototype. Это означает, что массивы – это просто объекты, но с дополнительными методами. Нет ничего такого, что делает объект, но не смог бы сделать массив.

Посмотреть пример

Странности

Как и у JavaScript объектов, у массивов есть свои особенности.

Неиндексированные свойства

Так как массивы – это просто объекты, к ним можно применять неиндексированные свойства. Обычно это первое, что удивляет. В примере ниже я устанавливаю два неиндексированных свойства с названиями sorted и authored by массиву groceries.

Примечание: как и в объектах, здесь поддерживается как точка, так и скобка.

Посмотреть пример

length

Свойство массива length также часто сбивает с толку. Часто это свойство путают с подсчетом элементов в массиве. Однако значение length в числовом выражении больше самого большого индекса массива. Из-за этого неиндексированные свойства не влияют на длину массива, как показано в примере.

Еще одна ситуация, в которой length может ввести в заблуждение, заключается в том, что мы пытаемся добавить элемент с индексом больше текущего значения массива length. Обратите внимание, что в примере length у массива прыгнул с 2 до 10 сразу после того, как добавил третий элемент в массив при индексе 9.

Когда значение свойства length изменяется, каждый элемент с индексом выше нового значения length подлежит удалению.

Примечание:

Чтобы получить корректное значение length, можно использовать Object.keys(groceries).length. Учтите, что это также включает неиндексированные свойства до тех пор, пока вы не определите их как не перечисляемые. То есть:

Object.defineProperty(groceries, "sorted", {
   value: false,
   enumerable: false,
   configurable: true,
   writable: true
});

Так как же быть?

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

Валентин Сейидовавтор-переводчик статьи «JavaScript: Arrays vs Objects»