Мы уже много раз говорили о многофункциональности JavaScript, но все еще остаются некоторые моменты которые не до конца ясны. К ним относятся логические несостыковки в математических уравнениях, Arrays и многом другом. С одной стороны может показаться, что создатели JavaScript не учли наличие и решение таких проблем. Давайте же заглянем в спецификации и посмотрим, где действительно скрывается причина подобных моментов.
Минимальное значение больше нуля
Number.MIN_VALUE – наименьшее число, которое больше нуля:
Number.MIN_VALUE=5e-324, т. е. наименьшее положительное число, которое может быть представлено с точностью до float – как можно ближе к нулю.
Теперь самое маленькое значение – Number.NEGATIVE_INFINITY, хотя оно не является действительно числовым в строгом смысле.
Функция – это не функция
Ошибка, присутствующая в V8 v5.5 или ниже (Node.js <=7).
Как насчет такого? Посмотрите на эти JavaScript строки:
Это не является частью спецификации, а просто ошибка, которая теперь исправлена, поэтому в будущем с ней не должно быть проблем.
Добавление массивов
Что произойдет, если вы попытаетесь вывести сумму двух массивов?
Конкатенация происходит. Если разбить ее на поэтапную модель, то выглядит все следующим образом:
Массив с плавающей запятой
Вы создали массив с четырьмя пустыми элементами. Несмотря на это, вы получите 3 элемента из-за плавающей запятой:
Трейлинг-запятые (также называемые «финальными запятыми») могут быть полезны при добавлении новых элементов, параметров или свойств в код JS. Хотите добавить новое свойство? Просто объявите новую строку без изменения предыдущей, если данная строка уже использует запятую. Такой подход значительно упростит работу, ведь само редактирование кода станет менее проблематичным.
- в MDN
Равномерность массива – монстр
Равномерность массива – это настоящий монстр в мире JS. Смотрите сами:
Вы должны быть очень осторожны! Это сложный пример, но он описан в спецификации 7.2.13. Абстрактное сравнение равенства.
undefined и Number
Если мы не передадим аргументы в конструктор Number, то получим 0. Значение undefined присваивается формальным аргументам, когда нет реальных, поэтому вполне ожидаемо, что Number без аргументов принимает значение undefined. Если же это неопределенность, мы однозначно получим результат в виде NaN.
- Если аргументы этой функции не были переданы, пусть n будет равно +0.
- Иначе что произойдет с n? ToNumber (value).
- В случае с undefined, ToNumber (undefined) должен возвращать NaN.
Также рекомендуем изучить соответствующие разделы:
parseInt – плохой парень
parseInt славится своими причудами:
Это происходит потому, что parseInt будет производить посимвольный синтаксический разбор до тех пор, пока не наткнется на символ, которого он не знает. f в ‘f *ck’ является шестнадцатеричной цифрой 15.
Парсинг Infinity в данной ситуации представляет собой нечто подобное:
Также будьте осторожны нулевым значением:
Да, JavaScript строки нередко ведут себя крайне странно: привыкайте. Приведенный выше пример конвертирует значение null в строку «null» и пытается его преобразовать. В интервале от 0 до 23 нет цифр, которые он может преобразовать, поэтому он возвращает NaN.
- из StackOverflow
Не забывайте и о восьмеричных значениях:
Если входная строка начинается с «0», то все зависит от поддержки ECMAScript 5, что возможно не во всех современных браузерах.
parseInt всегда конвертирует ввод в строку:
Математика с true и false
Давайте сгенерируем небольшой математический пример:
Мы можем закреплять за значениями числа с помощью конструктора Number. Совершенно очевидно, что true будет равно единице:
Оператор унарного плюса пытается преобразовать его значение в число. Он может преобразовывать JavaScript строки, с помощью которых реализовано представление целых чисел, и float. А еще, как видим, это могут быть значения, отличные от строки: true, false и null. Если он не может разобрать конкретное значение, в результате будет выдан NaN. Это означает, что мы можем все упростить:
Когда вы выполняете сложение или умножение, вызывается метод ToNumber. Согласно спецификации, этот метод возвращает:
- Если аргумент равен true, возвращается 1.
- Если аргумент false, возвращается +0.
Вот почему мы можем добавлять логические значения в виде регулярных чисел и получать правильные результаты.
Соответствующие разделы по теме:
HTML-комментарии возможны в JavaScript
Вы удивитесь, но <!– (который известен как комментарий HTML) является допустимым комментарием в JavaScript.
Впечатлены? HTML-подобные комментарии предназначены для того, чтобы браузеры, которые не понимают тег <script>, быстрее загибались. К таким можно отнести Netscape 1.x, который давно перестал быть популярным. Поэтому нет смысла добавлять HTML-комментарии в теги скриптов.
Поскольку Node.js основан на движке V8, комментарии, подобные HTML, также поддерживаются средой выполнения Node.js. Более того, они являются частью спецификации:
NaN не является числом
Тип NaN – это число:
Объяснения того, как работают операторы typeof и instanceof:
[] И null – объекты
Поведение оператора typeof подробно разъясняется в этом разделе спецификации:
Согласно спецификации, оператор typeof возвращает JavaScript строки в соответствии с таблицей 35: typeof Operator Results. Для нулевых, обычных и многих других объектов, которые не реализовывают [[Call]], он возвращает строку «object».
Тем не менее, вы можете проверить тип объекта с помощью метода toString.
Магически увеличивающиеся числа
Это вызвано стандартом IEEE 754-2008 для двоичной системы с плавающей запятой. В данном масштабе все округляется до ближайшего четного числа. Прочитайте больше:
Точность 0.1 + 0.2
Известная шутка. Добавление 0.1 и 0.2 является смертельно точным:
Константы 0.2 и 0.3 в вашей программе также будут приближаться к их истинным значениям. Бывает, что ближайший double к 0.2 больше, чем рациональное число 0.2, но ближайший double к 0.3 меньше рационального числа 0.3. Сумма 0.1 и 0.2 больше, чем рациональное число double и, следовательно, не согласуется с константой в вашем коде.
Эта проблема настолько известна, что есть даже сайт под названием 0.30000000000000004.com. Такое встречается в каждом языке, который использует математику с плавающей запятой, а не только JavaScript.
Патч-номера
Вы можете добавить свои собственные методы для обертки таких объектов, как Number или String.
Очевидно, вы можете экстендить объект Number, как и любой другой объект в JavaScript. Однако не рекомендуется это делать, если поведение определенного метода не является частью спецификации. Вот список свойств Number:
Сравнение трех чисел
Почему так? Ну, проблема в первой части выражения. Вот как это работает:
Мы можем исправить это с помощью оператора больше или равно (>=):
Подробнее о реляционных операторах в спецификации:
Смешная математика
Часто результаты арифметических операций в JavaScript могут быть довольно неожиданными. Рассмотрим следующие примеры:
Что происходит в первых четырех примерах? Вот небольшая таблица, чтобы понять принцип добавления в языке JavaScript:
Как насчет других примеров? Методы ToPrimitive и ToString неявно вызываются для [] и <> перед добавлением. Подробнее о процессе оценки в спецификации:
JavaScript строки не являются экземплярами String
Конструктор возвращает строку:
Попробуем с новым кодом:
JavaScript строки – объект? Что это?
Дополнительная информация о конструкторе String в спецификации: