Лучшее и самое подробное объяснение взаимосвязей JavaScript, которое я когда-либо видел

внешний интерфейс

banner

TLDR: заставьте себя использовать тройное равенство (===)

я не собираюсьRedditнашел это наJavaScript meme, это лучшая абстракция, которую я когда-либо видел.

tldr

Вы можете проверить точность этой связи, запустив инструменты разработчика для запуска каждой строки кода (на изображении). Результаты не удивили, но все же разочаровали.

Конечно же, этот небольшой эксперимент вызвал у меня интерес...

Как это произошло?

why-does-this-happen

С опытом я научился приниматьJavaScriptЭта забавная сторона, при этом чувствуя себя развязно. Тем не менее, подробности этого события сбивают меня с толку.

так какKyle Simpsonсказал...

«В любом случае, я не думаю, что кто-то действительно понимает JS»

В таких случаях лучше обратиться к исходному коду, который создает JavaScript.Официальная спецификация ECMAScript.

С этой спецификацией мы глубоко понимаем, что здесь происходит.

Тарелка 1-- введена обязательна

panel-1-1

Если вы работаете на консоли разработчиков0 == "0", почему он возвращаетсяtrue?

0это число, то"0"это строка, они никогда не должны быть одинаковыми! Большинство языков программирования ему подчиняются. Например,Javaсередина0 == "0", который возвращает следующее:

error: incomparable types: int and String

Это имеет смысл. Если вы хотите сравнитьJavaсерединаintа такжеString, они должны быть сначала преобразованы в один и тот же тип.

но этоJavaScript, ты!

this-is-javascript

когда ты проходишь==При сравнении двух значений одно из значений может подвергаться приведению.

Обязательный -автоматическийПреобразование значения из одного типа в другой.

здесьавтоматическийявляется ключевым словом.JavaScriptНе преобразовывать ваши типы явно, а делать это за вас за кулисами.

scumbag-javascript

Это удобно, если вы используете его целенаправленно, но может быть вредно, если вы не знаете, что это значит.

официально об этомСпецификация языка ECMAScript. Я объясню соответствующую часть:

If x is Number and y is String, return x == ToNumber(y)

Перевод: если x — числовой тип, а y — строковый тип, преобразовать y в числовой тип, сравнить его с x и вернуть

Итак, наш пример0 == "0":

Поскольку 0 — это числовой тип, а «0» — строковый тип, возвращаем 0 == ToNumber("0")

наша строка"0"был тайно преобразован в числа0, теперь у нас есть матч!

0 == "0" // true
// The second 0 became a number!
// so 0 equals 0 is true....

that-string-secretly-became-a-number

Странный? Привыкай, давай дальше

Табличка 2. Массивы также принудительно

panel-2

Эта сила не ограничивается только строкой, числом или другим базовым логическим типом данных. Это наше следующее сравнение:

0 == [] // true
// What happened...?

Опять принудительно! Я объясню соответствующую часть спецификации:

If x is String or Number and y is Object, return x == ToPrimitive(y)

Перевод: если x является строковым или числовым типом, то y является типом объекта, преобразуйте y в примитивный тип данных, сравните его с x и верните

Здесь есть три вещи:

1. Да, массивы — это объекты

arrays-are-objects

Извините, что освежил ваше понимание.

2. Пустой массив становится пустой строкой

опять такиСогласно спецификации, JS сначала ищет объектtoStringметод его литья.

В случае массивов,toStringОбъединяет все свои элементы и возвращает их в виде строк.

[1, 2, 3].toString() // "1,2,3"
['hello', 'world'].toString() // "hello,world"

Поскольку наш массив пуст, нам нечего конкатенировать! так...

[].toString() // ""

empty-array-coerces-to-empty-string-1

в спецификацииToPrimitiveПреобразование пустого массива в пустую строку. Связанные ссылки находятся вздесьа такжездесь, для вашего удобства (или чтобы разрешить сомнения).

3. Затем пустая строка становится 0

empty-strings-become-0

Вы не можете сделать это. Теперь мы привели массив в"", мы вернулись к первому алгоритму (норма)...

If x is Number and y is String, return x == ToNumber(y)

так0==""

Since 0 is Number and "" is String, return 0 == ToNumber("")

ToNumber("")Возвращает 0 .

Итак, это снова0==0...

coercion-every-time-2

Раздел 3 - Быстрый обзор

panel-3-1

это верно

0 == "0" // true

потому что быть брошенным на это0 == ToNumber("0").

Это также правильно

0 == [] // true

Потому что приведение выполняется дважды:

  1. ToPrimitive([])Преобразовать в пустую строку
  2. потомToNumber("")Преобразовать в 0 .

Итак, скажите мне... согласно приведенным выше правилам, что вернет следующее?

"0" == []

Блок 4 - ЛОЖЬ!

panel-4-1

НЕВЕРНО!

Эта часть имеет смысл, если вы понимаете правила.

Вот наше сравнение:

"0" == [] // false

Снова обратимся к спецификации:

If x is String or Number and y is Object, return x == ToPrimitive(y)

Это значит...

Since "0" is String and [] is Object, return x == ToPrimitive([])

"0" == ""

"0"а также""все строковые типы, поэтомуJavaScriptБольше лить не надо. Вот почему результатfalseпричина.

Суммировать

just-use-triple-equals

Используйте знак тройного равенства (===) и хорошо выспитесь.

0 === "0" // false
0 === [] // false
"0" === [] // false

Он полностью избегает броска, поэтому я думаю, что он также более эффективен!

Но ('===' for) прирост производительности практически бессмыслен. Настоящая победа — это дополнительная уверенность в коде, благодаря которой дополнительные движения по клавиатуре того стоят.

Ссылки и послесловия

Для получения дополнительной информации, пожалуйста, нажмитемой блогЧтобы узнать больше, будет лучше, если вы сможете оставить звезду 💨