Комментарии 20
Не пустой массив
Number([1, 2, 3])
приводится кNaN
Не так. Сначала на массиве выполняется .toString()
, а потом что получилось кастится в Number
. То-есть Number([1]) -> 1
, Number(['']) -> 0
.
Если перед вашим примером переопределить Array.prototype.toString = function(){return this.join('')}
, то Number([1,2,3])
вернёт 123, а не NaN.
typeof null
возвращает“object”
. Этот баг существует уже много лет
Это дичь и кривота, но не баг, а типа так задумано. Задумка была что null
это «не объект», нет объекта. То-есть его тип – объект, как у NaN тип – число.
Как раз таки баг, сам автор языка подтверждает это в комментариях тут: https://2ality.com/2013/10/typeof-null.html
Прекрасно, спасибо!
В своё оправдание – я инфу брал с MDN, там в https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#undefined_type как раз про absence of an object.
При этом в JavaScript 7 значений typeof
typeof 1n // => 'bigint'
Метод .toPrimitive вызывает valueOf у значения.
Абстрактная операция ToPrimitive
вызывает метод @@toPrimitive
, и только при его отсутствии - фаллбэк на .valueOf
и .toString
.
1 + { [Symbol.toPrimitive]() { return 1 }, valueOf() { return 2 }, toString() { return 3 }} // => 2
Строгое сравнение и сравнение с приведением типов
Забыли, например, про такой алгоритм сравнения, как SameValue
- Object.is
:
Object.is(NaN, NaN) // => true
Object.is(0, -0) // => false
Мы готовы рассмотреть интересные примеры, которые встречаются на собеседованиях
Интересный и далеко не всем известный пример для собеседования (не на джуна) это, например, document.all
:
typeof document.all // => 'undefined'
document.all === undefined // => false
document.all === null // => false
document.all == undefined // => true
document.all == null // => true
!document.all // => true
document.all instanceof HTMLAllCollection // => true
Не знаеье, случайно, почему именно у document.all
такое странное поведение? Выглядит уж очень магически, наверняка есть какая-то история.
Если коротко, то из-за обратной совместимости. ЕМНИП раньше это было специфичное для какого-то браузера (IE6?) API. При этом использовались конструкции вида
if (document.all) {
// old browser
} else {
// new browser
}
Потом это дело решили стандартизировать и что-бы не сломать код добавили такой костыль.
Не хватает коротких кастов !!x, ~~x, +x
Вы имеете в виду, не хватает совета так не писать? Магические значки не слишком способствуют пониманию кода, особенно в командах, где JS - не единственный язык.
Ну во-первых, это достаточно часто встречается в коде. Имо значительно чаще чем valueOf. Уж как минимум !!x вместо проверок на одновременно не-пустоту, не-null и не-undefined я вижу постоянно. Да и унарный плюс для приведения к числу тоже.
Во-вторых, эта "магия", как правило, работает примерно во всех языках с синтаксисом "в стиле Си" - Java, PHP и т.д. (хотя в языках со строгой типизацией часто не имеет особого смысла).
Уж как минимум !!x вместо проверок на одновременно не-пустоту, не-null и не-undefined я вижу постоянно.
Вы не фиксили баги, когда кто-то забыл, что !!x
не пропускает пустую строку или 0? Я фиксил.
Во-вторых, эта "магия", как правило, работает примерно во всех языках с синтаксисом "в стиле Си"
Приведите пример, если не сложно. Я не помню больше языков, где пишут ~~x
или !!x
.
не пропускает пустую строку или 0
До сих пор постоянно такое на фронтенде ловлю. Особенно в обработке пользовательского ввода)
!!x
не пропускает пустую строку или 0? Я фиксил.
ну так блин, фиксить надо кривые ручёнки. Если кодер не знает, что 0 это falsey-значение, то может его назад за учебники посадить? Учить, чем равны false и true, и что такое "пустая строка/массив". Про NaN молчу.
В пыхе подобное тоже довольно часто встречаю. Как и унарный плюс для каста к числу.
Ну ок, ~~x в js это больше подсказка компилятору. Явно не уровень тех, кто неосилил двойное отрицание :)
PS. Ну в общем сами говорите, что в коде это встречается. Поэтому, имо, неплохо было бы упомянуть в статье.
Ну ок, ~~x в js это больше подсказка компилятору. Явно не уровень тех, кто неосилил двойное отрицание
Я Не суперспец в js подскажите что вы имели ввиду, почему это подсказка компилятору? это же битовое отрицание, как это может быть связано с стадией компиляции если значение в рантайме считается? Или если js видит ~~ то на стадии компиляции происходит оптимизация на какую то логику которая отбрасывает дробную часть?
Именно. Все числа в JS по умолчанию имеют тип double (ну или BigInt). Если вы собираетесь делать какие-то тяжелые вычисления в 32-битных целых, то x = ~~x
это ваш способ сказать компилятору, что x
имеет тип int
.
И да, x сначала приводится к числу с плавающей точкой, а затем отбрасывается дробная часть.
Хм, ну такие баги скорее вызваны тем что человек забыл что 0 или '' - это допустимое значение переменной. Мне кажется в этом случае не использовать !! - не решает проблему
тот же человек может написать
if (value) {...}
и value будет либо пустой строкой либо 0. и будет тот же баг.
Если я правильно понял суть проблемы
Таблица с зелеными квадратиками - самый лучший-компактный способ описания логики языка.
А про
Значения
typeof
или я что то не понимаю или там какая то лажа, сначала написано что
”undefined”
как я понимаю значит typeof null равно (в смысле возвращает?) "undefined
"
а потом написано:
typeof null
возвращает "object"
Чему верить или что значит первый ”undefined”?
В общем можно сделать вывод что в основе языка js лежит таблица преобразований которую просто надо зазубрить, так исторически сложилось.
В начале статьи намешана в кучу иммутабельность и семантика передачи по значению или по ссылке.
let a = 1; let b = a; b += 1; console.log(a, b) // 1, 2 by value
let a = []; let b = a; b[0] = 1; console.log(a, b) // [1], [1] by reference
let a = [0]; a[0] = 1; console.log(a) // [1] mutable
let b = "0"; b[0] = 1; console.log(b) // "0" immutable
let a = 1
let b = "a"
let c = null
console.log(b || c) // null
Оператор || возвращает первый истинный операнд. Здесь получится "a" или изменить || на && чтобы было null.
typeof null === "object" никогда не был и не будет ошибкой языка js. Єто миф.
null в js єто именно обьект с неопределенной структурой. О чем прямо написано в спецификации.
при єтом возвращает тип null - primitive value. Что делает его лексически неоднозначным - єто так. Но єто не повод распространять миф о якобы ошибках. Єто повод прочесть официальную спецификацию - то есть документ который является єталонным врслучае описания норм языка
Особенности типов данных и преобразования в JavaScript