И объекты, и массивы играют несколько ролей в JavaScript. Этот пост в блоге объясняет, каковы эти роли.
Объекты и массивы представляют собой двойные структуры данных
Объекты: записи против карт
Объект JavaScript представляет собой комбинацию двух структур данных: иногда он используется как запись, иногда как словарь.
- Запись:
- Фиксированная форма (ключи известны заранее)
- Каждая запись (ключ, значение) имеет различное значение
- Дословные имена: Используйте имена буквально. Пример: obj.key
- Карта (словарь), от строк до произвольных значений:
- Гибкая форма (ключи обычно неизвестны заранее)
- Каждая запись (ключ, значение) имеет аналогичное значение
- Вычисляемые имена: обычно существует один уровень косвенности, вы не используете имена напрямую. Пример: obj [mykey] (mykey — переменная, которая содержит фактический ключ)
Массивы: кортежи и списки
Подобно объектам, массивы представляют собой комбинацию двух структур данных: иногда они используются в качестве кортежей, иногда в виде списков:
- Кортеж:
- Фиксированная длина
- Доступ к элементам напрямую по индексу
Пример: возвращение нескольких значений из функции или метода.
- Список:
- Динамическая длина
- Итерировать по всем элементам
сходства
Учитывая, что объект отображает имена в значения, а массив отображает натуральные числа в значения, очевидно, что записи и кортежи похожи. Их структура и диапазон одинаковы, отличается только их (функциональный) домен. То же самое касается карт и списков.
Смешение доменов «определение программы» и «данные приложения»
Объекты выполняют обязанности в двух областях: они иногда определяют программу, иногда содержат данные приложения.
- Область определения программы: Объект представляет собой структуру данных, содержащую логику программы. В основном они используются в качестве записей в этом домене.
- Область данных приложения. Объект представляет собой структуру данных, содержащую данные приложения. Объекты здесь используются в качестве записей и карт. Данные JSON являются частью этого домена.
Перекрытие двух доменов становится негативным, когда вы вызываете методы для объекта как карты, которые могут иметь произвольные ключи. Например, следующая функция заключается в том, как наивно реализовать проверку на наличие ключа:
function hasKey(obj, key) { return obj.hasOwnProperty(key); }
Нормальное использование:
> hasKey({foo: 123}, "foo") true
Однако эта функция перестает работать должным образом, если в obj используется ключ hasOwnProperty:
> hasKey({hasOwnProperty: 123}, "foo") TypeError: Property 'hasOwnProperty' of object #<Object> is not a function
Исправление заключается в следующем (есть другие вещи, на которые следует обратить внимание, о которых будет рассказано в следующем сообщении в блоге):
function hasKey(obj, key) { return Object.prototype.hasOwnProperty.call(obj, key); }
То есть вы обращаетесь к методу напрямую и не используете алгоритм поиска свойства, чтобы найти его.
Смешивание доменов с оператором []
Оператор [] был установлен в основном языке программирования как конструкция данных приложения. Только JavaScript смешивает домены: он используется для данных приложения в массивах и в объектах как карты. Но он также используется в качестве метапрограммирующего средства для доступа к свойству через вычисленное имя. Первый вариант использования настолько част, что имеет смысл позволить пользовательским типам коллекций переопределять оператор []. Чтобы избежать конфликта с последним вариантом использования (который встречается не часто), необходимо ввести методы, которые выполняют эту задачу. Например, Object.getProperty (имя) и Object.setProperty (имя, значение). В предложении ECMAScript.next «
Преобразование объектной модели: разделение [] и доступ к свойству » показано, как сделать это чисто.
Связанное чтение
Следующие письма в списке рассылки es-обсудили этот пост:
- « Разделение [] и доступ к свойствам для коллекций » (автор Аллен Уирфс-Брок) указывает на определение программы двух областей и данные приложения.
- « Выбор спецификации, разрушающий массив » (Дэвид Херман) упоминает запись против карты и кортеж против списка.