В этом разделе описаны операторы равенства и неравенства. Это операторы, сравнивающие два значения и возвращающие логическое значение (true или false) в зависимости от результата сравнения. Как мы увидим в главе 6, чаще всего они применяются в инструкциях if и циклах for для управления ходом ис_ полнения программы.
5.4.1. Равенство (==) и идентичность (===)
Операторы == и === проверяют две величины на совпадение, руководствуясь дву_ мя разными определениями совпадения. Оба оператора принимают операнды любого типа и возвращают true, если их операнды совпадают, и false, если они различны. Оператор ===, известный как оператор идентичности, проверяет два операнда на «идентичность», руководствуясь строгим определением совпаде_ ния. Оператор == известен как оператор равенства, он проверяет, равны ли два его операнда в соответствии с менее строгим определением совпадения, допус_ кающим преобразования типов.
84 Глава 5. Выражения и операторы
Оператор идентичности стандартизован в ECMAScript v3 и реализован в Java_ Script 1.3 и более поздних версиях. С введением оператора идентичности язык JavaScript стал поддерживать операторы =, == и ===. Убедитесь, что вы понимае_ те разницу между операторами присваивания, равенства и идентичности. Будь_ те внимательны и применяйте правильные операторы при разработке своих про_ грамм! Хотя очень заманчиво назвать все три оператора «равно», но во избежа_ ние путаницы лучше читать оператор = как «получается», или «присваивается», оператор == читать как «равно», а словом «идентично» обозначать оператор ===.
В JavaScript числовые, строковые и логические значения сравниваются по значе' нию. В этом случае рассматриваются две различные величины, а операторы==и === проверяют, идентичны ли эти два значения. Это значит, что две переменные равны или идентичны, только если они содержат одинаковое значение. Напри_ мер, две строки равны, только если обе содержат в точности одинаковые символы.
В то же время объекты, массивы и функции сравниваются по ссылке. Это зна_ чит, что две переменные равны, только если они ссылаются на один и тот же объ_ ект. Два различных массива никогда не могут быть равными или идентичными, даже если они содержат равные или идентичные элементы. Две переменные, со_ держащие ссылки на объекты, массивы или функции, равны, только если ссы_ лаются на один и тот же объект, массив или функцию. Для того чтобы прове_ рить, содержат ли два различных объекта одинаковые свойства или содержат ли два различных массива одинаковые элементы, надо их проверить на равенство или идентичность каждого свойства или элемента. (И если какое_либо свойство или элемент само является объектом или массивом, решить, на какую глубину вложенности вы хотите выполнять сравнение.)
При определении идентичности двух значений оператор === руководствуется следующими правилами:
• Если два значения имеют различные типы, они не идентичны.
• Два значения идентичны, только если оба они представляют собой числа, имеют одинаковые значения и не являются значением NaN (в этом, последнем случае они не идентичны). Значение NaN никогда не бывает идентичным ни_ какому значению, даже самому себе! Чтобы проверить, является ли значение значением NaN, следует использовать глобальную функцию isNaN().
• Если оба значения представляют собой строки и содержат одни и те же симво_ лы в тех же позициях, они идентичны. Если строки отличаются по длине или содержимому, они не идентичны. Обратите внимание, что в некоторых случа_ ях стандарт Unicode допускает несколько способов кодирования одной и той же строки. Однако для повышения эффективности сравнение строк в Java_ Script выполняется строго посимвольно, при этом предполагается, что все строки перед сравнением преобразованы в «нормализованную форму». Дру_ гой способ сравнения строк обсуждается в части III книги при описании мето_ да String.localeCompare().
• Если оба значения представляют собой логические значения true или false, то они идентичны.
• Если оба значения ссылаются на один и тот же объект, массив или функцию, то они идентичны. Если они ссылаются на различные объекты (массивы или функции), они не идентичны, даже если оба имеют идентичные свойства или идентичные элементы.
5.4. Операторы равенства
• Если оба значения равны null или undefined, то они идентичны.
Следующие правила применяются для определения равенства при помощи опе_ ратора ==:
• Если два значения имеют одинаковый тип, они проверяются на идентич_ ность. Если значения идентичны, они равны; если они не идентичны, они не равны.
• Если два значения не относятся к одному и тому же типу, они все же могут быть равными. Правила и преобразования типов при этом такие:
• Если одно значение равно null, а другое – undefined, то они равны.
• Если одно значение представляет собой число, а другое – строку, то строка преобразуется в число и выполняется сравнение с преобразованным значе_ нием.
• Если какое_либо значение равно true, оно преобразуется в 1 и сравнение выполняется снова. Если какое_либо значение равно false, оно преобразу_ ется в 0 и сравнение выполняется снова.
• Если одно из значений представляет собой объект, а другое – число или строку, объект преобразуется в элементарный тип и сравнение выполняет_ ся снова. Объект преобразуется в значение элементарного типа либо с по_ мощью своего метода toString(), либо с помощью своего метода valueOf(). Встроенные классы базового языка JavaScript сначала пытаются выпол_ нить преобразование valueOf(), а затем toString(), кроме класса Date, кото_ рый всегда выполняет преобразование toString(). Объекты, не являющие_ ся частью базового JavaScript, могут преобразовывать себя в значения эле_ ментарных типов способом, определенным в их реализации.
• Любые другие комбинации значений не являются равными.
В качестве примера проверки на равенство рассмотрим сравнение:
"1" == true
Результат этого выражения равен true, т. е. эти по_разному выглядящие значе_ ния фактически равны. Логическое значение true преобразуется в число 1, и сравнение выполняется снова. Затем строка "1" преобразуется в число 1. По_ скольку оба числа теперь совпадают, оператор сравнения возвращает true.
5.4.2. Неравенство (!=) и неидентичность (!==)
Операторы != и !== выполняют проверки, в точности противоположные операто_ рам == и ===. Оператор != возвращает false, если два значения равны друг другу, и true в противном случае. Оператор неидентичности !== возвращает false, если два значения идентичны друг другу, и true – в противном случае. Этот оператор стандартизован в ECMAScript v3 и реализован в JavaScript 1.3 и более поздних версиях.
Как мы увидим позднее, оператор ! осуществляет операцию логического НЕ. Благодаря этому легче запомнить, что != обозначает «не равно», а !== – «не иден_ тично». Подробности определения равенства и идентичности для разных типов данных рассмотрены в предыдущем разделе.