JavaScript: 5 странностей
о некоторых особенностях JavaScript, вызывающих нервный смех
Конечно, мы любим JavaScript. Это великолепный языка программирования. Но у него есть и “веселая” сторона, которая делает этот язык еще более интересным для изучения. В этой статье мы разберем 5 таких примеров.
И это не баги JavaScipt, а его особенности.
baNaNa
Как написать слово “banana”? В JavaScript для этого есть один нетривиальный способ:
let word = 'b' + 'a' + + 'a' + 'a';
console.log(word) // baNaNa
Как это работает?
Выражение 'b' + 'a' + + 'a' + 'a'
возвращает baNaNa
так как 'b' + 'a' + + 'a' + 'a'
преобразуется в 'b' + 'a' (+'a') + 'a'
, а (+'a')
в свою очередь соответствует не-числу NaN
. Это, в свою очередь, происходит из-за того, что оператор двоичного сложения пытается преобразовать операнд в число, но символ a
числом не является.
Математика логических значений
Итак, от цифр можно сильно устать, но для JavaScript - это не проблема. Всегда можно переключиться на true
и false
. В это языке программирования логические значения можно использовать для математических вычислений:
true + true; // -> 2
(true + true) * (true + true + true) // -> 6
Как это работает?
Конструктор Number
преобразует значения в числа. Таким образом true
превращается в 1, а false
превращается в 0.
Number(true); // 1
Number(false); // 0
Сходным образом унарный оператор +
пытается преобразовать любой операнд в число, в том числе и логические значения true
и false
.
+true // 1
+false // 0
Наконец, можно сказать, что при сложении или вычитании происходит автоматический вызов метода toNumber
, который в соответствии со спецификацией: для аргумента true
возвращает 1, а для агрумента false
возвращает 0.
Теперь понятно, почему математика с логическими значениями в JavaScript действительно работает?
NaN является числом
Давайте узнаем: какому типу данных в JavaScipt соответствует не-число (not-a-number) NaN
:
typeof NaN // 'number'
Действительно?
Как это работает?
Возможно, это покажется странным, но на самом деле NaN
является числом и используется в случаях, когда определенное значение не может быть представлено в рамках используемого числового типа. Другими словами, это число, которое не может быть описано.
Доступ к свойствам через массив
Получить доступ к значению по индексу можно, поместив в оператор []
число или строку. Но, также, для этих целей можно использовать и массив:
let data = { number: 1 },
array = ["number"];
console.log(data[array]); // -> 1
Как это работает?
Это работает, потому что оператор []
всегда запускает метод toString
и преобразует аргумент в строку. А в JavaScript приведение массива, состоящего из одного элемента, в строку всегда вернет строку, соответствующую значению первого элемента массива.
Например:
console.log(["test"].toString()); // test
Сортировка
Задача кажется простой: достаточно отсортировать массив числе с помощью метода sort()
:
[1, 5, 2, 10, 30].sort();
Результат:
[1, 10, 2, 30, 5]
Неужели JavaScript считает, что числа действительно отсортированы?
Как это работает?
И это не баг. По умолчанию метод sort()
преобразует элементы массива в строки, после чего сравнивает и сортирует их значения в формате UTF-16. Поэтому, если действительно нужно провести сортировку значений, отличных от string
, необходимо передать в метод сортировки функцию сравнения:
console.log([1,5,2,10,30].sort((a, b) => a - b));
// [1, 2, 5, 10, 30]
Спасибо за внимание.
Перевод статьи “5 JavaScript WTFs”.