Приведение типов и операторы
Приведение типов и к булеву, нестрогое против строгого равенства и семейства операторов — логические, побитовые, унарные.
10 вопросов
MiddleТеорияОчень частоВ чём разница между == и ===?
В чём разница между == и ===?
=== (строгое) сравнивает значение и тип без преобразования, поэтому разные типы никогда не равны. == (нестрогое) сначала приводит операнды к общему типу, поэтому 0 == '', 1 == '1' и null == undefined равны true. NaN не равен ничему, а +0 === -0 даёт true.
Типичные ошибки
- ✗Считать, что
===выполняет приведение — он никогда не преобразует типы - ✗Думать, что
NaN === NaNэтоtrue - ✗Полагать, что
==сравнивает содержимое объектов, а не ссылку
Уточняющие вопросы
- →Разберите, как
==приводит обе стороны в[] == ![]. - →Почему
+0 === -0это true, аObject.is(+0, -0)это false?
MiddleТеорияОчень частоКакое значение возвращают &&, || и ?? и как они короткозамкнуты?
Какое значение возвращают &&, || и ?? и как они короткозамкнуты?
Эти операторы короткозамкнуты и возвращают один из операндов, а не приведённое булево. && возвращает первый ложный операнд или последний, если все истинные. || возвращает первый истинный операнд, иначе последний. ?? возвращает правую часть, только когда левая null или undefined, игнорируя прочие ложные значения. Поэтому 0 || 'x' это 'x', а 0 ?? 'x' это 0.
Типичные ошибки
- ✗Считать, что операторы возвращают булево, а не один из операндов
- ✗Путать
??с||, забывая, что он проверяет лишьnull/undefined - ✗Думать, что обе стороны всегда вычисляются, упуская пропуск при замыкании
Уточняющие вопросы
- →Что возвращает
'' && 'x'и почему замыкание останавливается раньше? - →Когда
??и||дадут разный результат для одного левого операнда?
JuniorТеорияЧастоЧто такое неявное приведение типов в JavaScript?
Что такое неявное приведение типов в JavaScript?
Неявное приведение — это автоматическое преобразование операнда к другому типу для выполнения операции. + со строкой приводит другую сторону к строке (1 + '2' это '12'); прочая арифметика и сравнения приводят к числу ('3' * 2 это 6). В булевом контексте значение приводится к truthy или falsy.
Типичные ошибки
- ✗Считать, что
+всегда численный — со строковым операндом он конкатенирует - ✗Думать, что
===выполняет приведение (он никогда этого не делает) - ✗Ожидать, что приведение выбросит ошибку при несовпадении типов, а не молча преобразует
Уточняющие вопросы
- →Почему
1 + '2'даёт'12', а'3' * 2даёт6? - →В чём разница между
Number(x)и унарным+x?
JuniorТеорияЧастоКакие значения являются ложными (falsy) в JavaScript и что делает !!x?
Какие значения являются ложными (falsy) в JavaScript и что делает !!x?
8 ложных значений: false, 0, -0, 0n, '', null, undefined и NaN; всё остальное истинно, включая '0', [] и {}. !!x применяет логическое НЕ дважды, приводя любое значение к булеву эквиваленту — true, если оно истинно, и false, если ложно.
Типичные ошибки
- ✗Думать, что
'0',[]или{}ложны — все они истинны - ✗Забывать, что
NaN,-0и0nложны - ✗Считать, что
!!xвозвращает значение, а не булево
Уточняющие вопросы
- →Почему пустой массив
[]истинен, хотя[] == falseдаётtrue? - →Чем
!!xотличается отBoolean(x)?
JuniorТеорияИногдаКакие основные категории операторов есть в JavaScript?
Какие основные категории операторов есть в JavaScript?
Операторы JavaScript группируют по назначению: арифметические (+ - * / % **), сравнения (< > == ===), логические (&& || ! ??), битовые (& | ^ ~ << >>), присваивания (= += &&=), тернарный ?: и оператор запятая. Они различаются и по арности: большинство бинарные, но ! и typeof унарные, а ?: тернарный.
Типичные ошибки
- ✗Думать, что
?:— лишь синтаксис дляif, а не оператор, дающий значение - ✗Считать, что логические операторы всегда возвращают булево, а не один из операндов
- ✗Полагать, что в JavaScript нет битовых операторов, ведь числа — с плавающей точкой
Уточняющие вопросы
- →Какова арность
?:и почему это важно? - →К какой категории относится
??и чем он отличается от||?
JuniorТеорияИногдаКакие унарные операторы есть в JavaScript и что делает каждый?
Какие унарные операторы есть в JavaScript и что делает каждый?
Унарный оператор берёт один операнд. typeof x возвращает строку типа, например number. delete obj.k удаляет собственное свойство. void expr вычисляет expr и возвращает undefined. !x приводит к булеву и инвертирует его. Унарный +x преобразует в число (+'5' это 5), а унарный -x отрицает численно. ++/-- увеличивают или уменьшают на месте.
Типичные ошибки
- ✗Думать, что
deleteосвобождает переменную или память, а не удаляет собственное свойство - ✗Ожидать, что
voidвозвращаетnull, а не всегдаundefined - ✗Забывать, что унарные
+/-приводят к числу, поэтому+'5'это5, а не'5'
Уточняющие вопросы
- →Что возвращает
deleteпри попытке удалить неконфигурируемое свойство? - →Почему
void 0иногда используют как безопасный способ получитьundefined?
MiddleТеорияИногдаКак работают тернарный ?: и оператор запятая в JavaScript?
Как работают тернарный ?: и оператор запятая в JavaScript?
Тернарный cond ? a : b — единственный оператор с тремя операндами: он вычисляет cond, затем возвращает a, если истинно, иначе b, и это выражение, дающее значение. Оператор запятая a, b, c вычисляет каждый операнд слева направо, но возвращает только значение последнего, поэтому (1, 2, 3) это 3. Промежуточные операнды выполняются ради побочных эффектов.
Типичные ошибки
- ✗Думать, что
?:— инструкция, а не выражение, возвращающее значение - ✗Считать, что оператор запятая возвращает первый операнд, а не последний
- ✗Забывать, что тернарный вычисляет только выбранную ветку
Уточняющие вопросы
- →Как оператор запятая позволяет циклу
forобновлять две переменные сразу? - →Почему тернарные можно вкладывать и когда это вредит читаемости?
SeniorТеорияИногдаКак нестрогое равенство приводит операнды? Разберите [] == ![].
Как нестрогое равенство приводит операнды? Разберите [] == ![].
== следует шагам абстрактного равенства: null == undefined — особый случай, всегда true; сравнение число-строка приводит строку к числу; булев операнд сначала приводится к числу; сравнение объект-примитив приводит объект через ToPrimitive. Для [] == ![]: ![] это false, затем 0; [] становится '', затем 0; поэтому 0 == 0 это true.
Типичные ошибки
- ✗Сравнивать истинность сторон напрямую вместо того, чтобы идти по шагам приведения
- ✗Забывать, что булев операнд приводится к числу перед сравнением
- ✗Считать, что объект сравнивается по своему JSON, а не через
ToPrimitive
Уточняющие вопросы
- →Почему
[] == ''выполняется, а[] === ''— нет? - →Как
ToPrimitiveвыбирает междуvalueOfиtoStringобъекта?
SeniorТеорияИногдаКак приоритет и ассоциативность операторов определяют порядок вычисления в JavaScript?
Как приоритет и ассоциативность операторов определяют порядок вычисления в JavaScript?
Приоритет решает, какой оператор связывает сильнее без скобок, поэтому * выполняется раньше + в 1 + 2 * 3. Ассоциативность разрешает ничью между операторами равного приоритета: большинство левоассоциативны, но =, ** и ?: правоассоциативны. Приоритет управляет лишь группировкой, а не порядком вычисления операндов слева направо. Частые ловушки — ** сильнее унарного - и && сильнее ||.
Типичные ошибки
- ✗Путать приоритет (группировку) с порядком вычисления операндов (он слева направо)
- ✗Считать
=,**и?:левоассоциативными, как большинство операторов - ✗Забывать, что
&&сильнее||, что меняет группировку условий
Уточняющие вопросы
- →Почему
-2 ** 2— синтаксическая ошибка и как записать это правильно? - →Как правоассоциативность заставляет
a = b = cприсваивать справа?
MiddleТеорияРедкоКакие битовые операторы есть в JavaScript и что делает приём ~~?
Какие битовые операторы есть в JavaScript и что делает приём ~~?
Битовые операторы: & (И), | (ИЛИ), ^ (XOR), ~ (НЕ), << (сдвиг влево), >> (сдвиг вправо с сохранением знака) и >>> (сдвиг вправо с заполнением нулями). Они сначала приводят операнды к 32-битным знаковым целым, отбрасывая дробную часть. Поэтому двойное ~~x усекает к нулю как Math.trunc, например ~~4.9 это 4, а ~~-4.9 это -4.
Типичные ошибки
- ✗Забывать, что битовые операторы сначала приводят операнды к 32-битным знаковым целым
- ✗Путать
~~x(усечение) с округлением какMath.round - ✗Считать
>>и>>>одинаковыми, игнорируя обработку знака
Уточняющие вопросы
- →Почему
~~xневерно усекает числа больше 2³¹−1? - →Чем
>>>отличается от>>, когда операнд отрицательный?