Мы видели, как доступ к свойствам объекта осуществляется посредством оператора «точка». Доступ к этим свойствам возможен также при помощи оператора [], который обычно применяется при работе с массивами. Таким образом, следующие два выражения JavaScript имеют одинаковое значение:
object.property
object["property"]
Важное различие между этими двумя синтаксисами, на которое следует обратить внимание, состоит в том, что в первом варианте имя свойства представляет собой идентификатор, а во втором – строку. Скоро мы узнаем, почему это так важно.
В Java, C, C++ и подобных языках с сильной типизацией объект может иметь только фиксированное число свойств, и имена этих свойств должны быть определены заранее. JavaScript – это язык со свободной типизацией, поэтому к нему данное правило не применяется, – программа может создавать любое количество свойств в любом объекте. Однако в случае применения оператор «точка» для доступа к свойству объекта имя свойства задается идентификатором. Идентификаторы должны быть частью текста программы на JavaScript – они не являются типом данных и ими нельзя манипулировать из программы.
С другой стороны, при обращении к свойству объекта с помощью нотации массивов [] имя свойства задается в виде строки. Строки – это тип данных JavaScript, поэтому они могут создаваться и изменяться во время работы программы. И поэтому можно, например, написать в JavaScript следующий код:
var addr = "";for(i = 0; i < 4; i++) {
addr += customer["address" + i] + '\n';
}
В этом коде читаются и конкатенируются свойства address0, address1, address2 и address3 объекта customer.
Этот короткий пример демонстрирует гибкость нотации массивов при обращении к свойствам объекта с помощью строковых выражений. Мы могли написать этот пример и с оператора «точка», но есть ситуации, где подойдет только нотация массивов. Предположим, что вы пишете программу, обращающуюся к сетевым ресурсам для вычисления текущей суммы инвестиций пользователя на фондовом рынке. Программа разрешает пользователю вводить названия любых имеющихся у него акций, а также количество каждого вида акций. Можно организовать хранение этой информации при помощи объекта с именем portfolio. Объект имеет по одному свойству для каждого вида акций. Имя свойства – это название акции, а значение свойства – количество акций данного вида. Другими словами, если, например, у пользователя имеется 50 акций IBM, то свойство portfolio.ibm имеет значение 50.
Частью этой программы должен быть цикл, запрашивающий у пользователя название имеющихся у него акций, а затем количество акций данного типа. Внутри цикла должен быть код, похожий на следующий:
var stock_name = get_stock_name_from_user();
var shares = get_number_of_shares();
portfolio[stock_name] = shares;
Пользователь вводит названия акций во время выполнения, поэтому нет способа узнать имена свойств заранее. А раз имена свойств при написании программы неизвестны, то доступа к свойствам объекта portfolio при помощи оператора «точка» невозможен. Однако можно обратиться к оператору [], так как в нем для имени свойства используется строковое значение (которое может изменяться во время выполнения), а не идентификатор (который должен быть задан непосредственно в тексте программы).
Когда объект используется в такой форме, его часто называют ассоциативным массивом – структурой данных, позволяющей связывать произвольные значения с произвольными строками. Объекты JavaScript на самом деле внутренне реализованы как ассоциативные массивы. Нотация «.» для доступа к свойствам делает их похожими на статические объекты C++ и Java, и они прекрасно работают в этой роли. Но они также предоставляют мощное средство для связи значений с произвольными строками. В этом отношении объекты JavaScript значительно больше похожи на массивы в Perl, чем на объекты C++ или Java.
В главе 6 был введен цикл for/in. Настоящая мощь этой конструкции JavaScript становится понятной, если рассмотреть ее применение с ассоциативными массивами. Возвращаясь к примеру с портфелем акций, после ввода пользователем данных по своему портфелю вычислить текущую общую стоимость последнего можно при помощи следующего кода:var value = 0;
for (stock in portfolio) {
// Для каждого вида акций в портфеле получаем стоимость одной акции
// и умножаем ее на число акций.
value += get_share_value(stock) * portfolio[stock];
}
Здесь не обойтись без цикла for/in, поскольку названия акций заранее не известны. Это единственный способ извлечения имен этих свойств из ассоциативного массива (или объекта JavaScript) по имени portfolio.