Я только начал изучать JavaScript на более глубоком уровне и натолкнулся на множество концепций, которые делают JavaScript уродливым языком. Это будет набор элементов JavaScript (концепций / синтаксиса / ошибок), которые заставят любого человека ненавидеть его изучение.

Нулевое значение имеет тип объекта!

Чем страннее это звучит, тем правдивее!
Но это всего лишь ошибка, и она существует так давно, что теперь, если она будет исправлена, это может помешать работе многих приложений и написанного на ней кода.

Вы либо умираете героем, либо живете достаточно долго, чтобы увидеть себя злодеем.

Хотя любой человек в обычном смысле слова не хотел бы полагаться на typeof() потенциально нулевого объекта как на "object", чтобы подтвердить его нулевое значение. Но все же, кто знает! Есть люди, которые пробуют такое. "Узнать больше!"

Переопределенные ключи и строковое принуждение ключей

Любой человек будет ожидать «String Zero» и «Number Zero» последовательно, но он регистрирует «Number Zero» оба раза. Потому что

  1. Все ключи внутренне приведены к строкам, поэтому и «0», и «0» должны означать одно и то же.
  2. В объектах JavaScript последний ключ переопределяет все предыдущие ключи с тем же строковым значением.

Приведение массива к строкам

Причина такого поведения очень проста.

  1. И a, и b равны c, потому что при сравнении массива и строки массив преобразуется в строку как значения, разделенные запятыми.
  2. Хотя и a, и b имеют одни и те же массивы, внутренние значения являются просто ссылками на память, содержащую эти массивы. Если оба они не имеют одинакового эталонного значения, они никогда не будут равны.

Упрямое поведение NaN

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

Внутренний порядок действий можно интерпретировать как

a == b
42 == "foo"
42 == Number("foo")
42 == NaN     // NaN - Because "foo" can't become any number

Если вы хотите углубиться в NaN, см. this

Нет подъема на прокат

Это нормально ожидать, что let будет действовать так же, как var и переменные будут подняты. Но каждый оператор let рассматривается как обычный оператор присваивания, поэтому он выполняется, когда встречается строка. Что поднимает?

Функциональные выражения не поднимаются

Выражения функций не поднимаются, но мы не получаем ReferenceError, а TypeError, и причина в том, что переменная foo поднимается как обычно, но значение остается неопределенным до тех пор, пока выполнение не достигнет строки назначения функции. Поскольку мы предполагаем, что переменная является функцией и вызывается, она вызывает ошибку TypeError, поскольку foo не является функцией. "Узнать больше!"

Но

Теперь он выдает ошибку ReferenceError, потому что, поскольку мы не использовали var или let при объявлении foo, он добавляется к глобальному объекту и, таким образом, становится глобальной переменной (на самом деле это становится свойством глобального объекта), и это происходит, когда механизм javascript встречает ту самую строку, в которой объявлена ​​переменная. Поэтому, когда перед этим вызывается foo, поскольку такая переменная существует, он выдает ошибку ReferenceError. См. - Ужас неявных глобалов

Закрытие

Учти это

Функция alpha() возвращает ссылку на свою внутреннюю функцию beta(), которая имеет доступ к ее внутренней переменной a. Теперь, когда мы вызываем alpha() и назначаем его вывод на gamma(), он обращается к beta()

Обычно мы ожидаем, что вся внутренняя область видимости alpha() исчезнет, ​​потому что мы знаем, что движок JavaScript использует сборщик мусора, который появляется и освобождает память, когда она больше не используется. Поскольку может показаться, что содержимое alpha() больше не используется, кажется естественным, что его следует считать утерянным.

Но нет!.

В силу того, где оно было объявлено, beta() имеет закрытие лексической области над внутренней областью alpha(), что сохраняет эту область видимости, чтобы beta() мог ссылаться на нее в любое время.

beta() по-прежнему имеет ссылку на эту область, и эта ссылка называется закрытием.

Позже, когда вызывается переменная gamma (вызывая внутреннюю функцию, которую мы изначально обозначили как beta), она должным образом имеет доступ к лексической области видимости автора, так что она может получить доступ к переменной a, как мы и ожидали. Узнай глубже!

Продолжение следует…

P.S: Я действительно не против изучать JavaScript. У него есть недостатки, и нам нужно от них двигаться дальше. Ведь ядро написано за 10 дней!