Как стать автором
Обновить

Комментарии 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 тип – число.

При этом в 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

или я что то не понимаю или там какая то лажа, сначала написано что

  1. ”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

в JavaScript нет передачи по значению. То есть абсолютно все передается по ссылке.

В єтом легко убедиться как проведя пару простых опытов, так и прочитав официальную спецификацию раздел идентификаторы

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. Что делает его лексически неоднозначным - єто так. Но єто не повод распространять миф о якобы ошибках. Єто повод прочесть официальную спецификацию - то есть документ который является єталонным врслучае описания норм языка

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории