Как мы все знаем, == в JavaScript является относительно сложной операцией. Его правила эксплуатации очень странные и могут легко допустить ошибки, что делает его одной из худших функций в JavaScript.
Основываясь на тщательном чтении спецификации Ecmascript, я нарисовал картинку. Я подумал, что после того, как вы поймете эту картину, вы полностью поймете все о операции ==. В то же время я пытался доказать всем в этой статье, что == не так уж и плохо. Это легко освоить и даже выглядеть разумно и не так уж и плохо.
Во -первых, изображение:
== Точное описание правил работы здесь: Алгоритм сравнения абстрактного равенства. Однако, с таким сложным описанием, вы уверены, что не почувствуете головокружение после прочтения? Можете ли вы использовать его, чтобы немедленно направлять свою практику?
Это, конечно, не работает. В конце концов, спецификация предназначена для разработчиков среды управления JavaScript (по сравнению с разработчиками двигателей V8), а не для пользователей языков. На картинке выше переводится спецификация в форму, которая удобна для всех.
Перед тем, как представить каждую часть на рисунке 1 подробно, давайте рассмотрим знания о типах в JS:
В JS есть два типа значений: базовый тип и тип объекта.
Основные типы включают в себя: неопределенные, нулевые, логические, число и строка.
Как неопределенный тип, так и нулевый тип имеют только одно значение, а именно неопределенное и нулевое; Логический тип имеет два значения: true и false; Есть много значений типа числа; и тип строки имеет бесчисленные значения (теоретически).
Все объекты имеют методы значения () и toString (), которые унаследованы от объекта и, конечно, могут быть переписаны подклассами.
Теперь рассмотрим выражение:
x == y
где x и y являются значениями одного из шести типов.
Когда типы x и y одинаковы, x == y может быть преобразовано в x === y, а последнее очень просто (единственное, что нужно отметить, - это NAN), поэтому ниже мы рассмотрим только случаи, когда типы x и y разные.
1. Им есть и нет
На рисунке 1 шесть типов значений JavaScript представлены прямоугольниками с синим фоном. Сначала они разделены на две группы:
Строка, номер, логический и объект (соответствующий большой прямоугольной коробке слева)
Неопределенная и нулевая (соответствующая прямоугольной коробке справа)
Что является основой для группировки? Давайте посмотрим. Неопределенные и нулевые справа используются для обозначения неопределенности, не являются или пустыми, в то время как четыре типа справа определяются, существуют и не пустые. Мы можем сказать это:
Слева - это мир существования, а справа - пустой мир.
Следовательно, разумно сравнить любую ценность в двух мирах с ложными. (т.е. горизонтальная линия, соединяющая два прямоугольника на рисунке 1, помечена ложно)
2. пусто и пусто
Неопределенные и нулевые в JavaScript - это еще одно место, которое часто нас разрушает. Обычно это считается недостатком дизайна, в который мы не будем копаться. Но я слышал, что автор JavaScript изначально думал об этом:
Если вы планируете присвоить переменную значению типа объекта, но еще не присваивали значение, то вы можете использовать NULL для представления состояния в настоящее время (одним из доказательств является то, что результатом типа NULL является «объект»); Напротив, если вы планируете присвоить переменную значению исходного типа, но еще не присваивали значение, вы можете использовать неопределенное для представления состояния в настоящее время.
Независимо от того, является ли этот слух достоверным или нет, разумно, что результат сравнения между ними правда. (т.е. истинный отмечен на вертикальной линии справа на рисунке 1)
Прежде чем перейти к следующему шагу, давайте поговорим о двух символах на рисунке 1: Заглавные буквы n и P. Эти два символа не означают положительных и отрицательных в разделе PN. Вместо:
N представляет собой работу тонумбер, что означает преобразование операнда в число. Это абстрактная операция в спецификации ES, но мы можем использовать функцию number () в JS, чтобы эквивалентно заменить ее.
P представляет собой топримитивную операцию, то есть преобразование операнда в значение исходного типа. Это также абстрактная операция в спецификации ES, и ее также можно перевести в эквивалентный код JS. Но это немного сложнее. Проще говоря, для объекта obj:
Toprimitive (obj) эквивалентен: сначала рассчитать obj.valueof (), если результатом является исходное значение, этот результат возвращается; В противном случае рассчитывается obj.toString (), и если результатом является исходное значение, этот результат возвращается; В противном случае исключение брошено.
Примечание. Здесь есть исключение, то есть объект даты типа, который сначала вызовет метод ToString ().
На рисунке 1 строка, помеченная N или P, указывает, что, когда два типа данных подключены для выполнения операции ==, операнд на стороне, отмеченной N или P, должен сначала выполнить тонубер или тонеримитирующий преобразование.
3. Верно и неверно
Как видно из рисунка 1, когда логическое значение сравнивается с другими типами значений, логическое значение преобразуется в число. Конкретно
Верно -> 1
false -> 0
Это вообще не требует слишком много словесных оскорблений. Подумайте об этом, в C, нет логического типа вообще. Целые числа 1 и 0 обычно используются для представления истинной или ложной логики.
IV Последовательность символов
На рисунке 1 мы делим строку и число на группу. Почему? Среди шести типов строка и число являются последовательностями символов (по крайней мере, буквально). Строка - это последовательность всех юридических символов, в то время как число можно рассматривать как последовательность символов, которые соответствуют определенным условиям. Следовательно, числа могут рассматриваться как подмножество строк.
Согласно рисунку 1, при выполнении операции == строк и чисел необходимо использовать операцию тонумбер, чтобы преобразовать строку в числа. Предполагая, что x - это строка, а y - это число, тогда:
x == y -> число (x) == y
Так каково правило для преобразования строк в числа? Спецификация описывается очень сложным образом, но, вообще говоря, она должна удалить кавычки с обеих сторон строки и посмотреть, сможет ли она сформировать юридическое число. Если так, то результат конверсии - это число; В противном случае, результат - Нэн. Например:
Номер ('123') // Результат 123
Номер ('1.2e3') // Результат 1200
Номер ('123ABC') // Результат NAN
Конечно, есть исключения, такие как результат преобразования пустой строки в число, составляет 0. Прямо сейчас
Номер ('') // Результат 0
V. Простые и сложные
Примитивные типы - это простые типы, они просты и просты для понимания. Тем не менее, недостаток заключается в том, что способность выражения ограничена и трудно расширить, поэтому есть объекты. Объект представляет собой набор атрибутов, и сам атрибут может быть объектом. Поэтому объекты могут быть построены произвольно сложными, чтобы представлять различные вещи.
Но иногда все сложно и не очень хорошая вещь. Например, не у всех есть время, терпение или необходимость читать его от начала до конца. Обычно этого достаточно, чтобы понять его только центральные мысли. Таким образом, в газете есть ключевые слова и обзоры. То же самое относится и к объектам в JavaScript. Нам нужно иметь средства для понимания его основных характеристик, поэтому объекты имеют методы ToString () и значение ().
Метод ToString () используется для получения текстового описания объекта; и метод значения () используется для получения собственного значения объекта.
Конечно, это только мое собственное понимание. Кроме того, как следует из названия, метод ToString () имеет тенденцию возвращать строку. Как насчет метода значения ()? Согласно описанию в спецификации, он имеет тенденцию возвращать число - хотя в встроенном типе метод значения () возвращает только число и дату.
Согласно рисунку 1, когда объект сравнивается с некомъектом, объект должен быть преобразован в примитивный тип (хотя при сравнении с логическим типом логический тип должен быть сначала преобразован в числовой тип, но тип объекта должен быть преобразован в примитивный тип следующим). Это также разумно. В конце концов, == не является строго равным сравнением. Нам нужно только извлечь основные функции объекта для участия в операции и отложить в сторону вторичные функции.
Шесть. Все учитывается
Давайте посмотрим на рисунок 1. Линии, отмеченные N или P внутри, не имеют направления. Если мы отмечаем стрелки на этих линиях, точки подключения от конца отмечены n или p к другому концу, то мы получим (не рассматривая неопределенные и нулевые):
Вы что -нибудь обнаружили? Да, во время процесса расчета все типы значений имеют тенденцию конвертировать в числовые типы. В конце концов, знаменитость однажды сказала:
Все учитывается.
7. Просто дай мне каштан
В прошлом слишком много чушь, поэтому вот пример, чтобы доказать, что рисунок 1 действительно удобен и эффективен для руководства практикой.
Пример, рассчитайте следующее:
[''] == Неверно
Во -первых, эти два операнда являются типом объекта и логическим типом соответственно. Согласно рисунку 1, необходимо преобразовать логический тип в числовой тип, а результат преобразования FALSE в число - 0, поэтому выражение становится:
[''] == 0
Два операнда становятся типом объекта и числовым типом. Согласно рисунку 1, тип объекта должен быть преобразован в исходный тип:
Сначала позвоните [] .valueof (). Поскольку метод значения () массива возвращается, результатом является не исходный тип. Продолжайте звонить [] .toString ().
Для массивов алгоритм метода toString () заключается в преобразовании каждого элемента в тип строки, а затем объединить его с ',', так что конечным результатом является пустая строка, которая является значением исходного типа.
На этом этапе выражение становится:
'' == 0
Два операнда становятся типами строк и числовыми типами. Согласно рисунку 1, тип строки должен быть преобразован в числовые типы. Как упоминалось ранее, пустая строка становится несколькими 0. Таким образом, выражение становится:
0 == 0
До сих пор типы двух операндов наконец -то одинаковы, и результат, очевидно, верен.
Из этого примера мы видим, что для того, чтобы овладеть правилами операции ==, в дополнение к запоминанию рисунка 1, мы также должны помнить правила ToString () и значение () методов этих встроенных объектов. Включая объект, массив, дату, номер, строка, логический и т. Д.
8. Давайте суммируем
Предыдущее заявление очень запутанно. Здесь я суммирую правила операции ==, выраженная на рисунке 1:
Результат неопределенного == NULL верно. Результатом их сравнения со всеми другими значениями является ложным.
Когда номер строки ==, строка преобразуется в число.
Логическое значение == Когда используются другие типы, логическое значение преобразуется в число.
Когда объект == numeric/string, объект преобразуется в примитивный тип.
Наконец, я изменил картину только для развлечения :)
Хорошо, все кончено. Если вы думаете, что эта статья полезна для вас, пожалуйста, чтобы она могла ее увидеть.
Кроме того, укажите ошибки в статье.