Что делает оператор двойного восклицательного знака (!!) в JavaScript? Я столкнулся с этим фрагментом кода:
this.vertical = vertical !== undefined ? !!vertical : this.vertical;
Похоже, что здесь используется !! как оператор, с которым я не знаком. Можете объяснить, что делает этот оператор и как он работает в JavaScript?
Оператор двойного восклицательного знака (!!) в JavaScript — это сокращенный метод для преобразования любого значения в его булев эквивалент. Он работает путем применения оператора логического НЕ дважды: сначала преобразуя значение в булев тип и инвертируя его, а затем инвертируя результат обратно к исходному булевому значению. Этот оператор commonly используется для обеспечения последовательного булевого при работе со значениями, которые являются истинными (truthy) и ложными (falsy).
Содержание
- Понимание оператора двойного восклицательного знака
- Как работает оператор !!
- Истинные и ложные значения
- Практические примеры
- Сравнение с функцией Boolean()
- Распространенные случаи использования
- Вопросы производительности
Понимание оператора двойного восклицательного знака
Оператор двойного восклицательного знака (!!) в JavaScript не является самостоятельным оператором — это на самом деле два последовательных применения оператора логического НЕ (!). Этот часто называют “двойной банг” (double bang) разработчики. Основная цель этого шаблона оператора — преобразовать любое значение JavaScript в его булев эквивалент.
Как объясняется в обсуждении на Stack Overflow, оператор !! по сути является сокращенным методом приведения переменных к булевому значению (true или false). Этот шаблон особенно полезен, когда вам явно нужно работать с булевыми значениями, а не полагаться на оценку JavaScript истинных/ложных значений.
Как работает оператор !!
Оператор двойного восклицательного знака работает через двухэтапный процесс:
- Первый оператор !: Преобразует значение в булев тип и инвертирует его
- Второй оператор !: Инвертирует результат снова, возвращая исходное булево значение
Давайте разберем это на конкретном примере:
const value = "hello";
const result = !!value;
// Шаг 1: !"hello" → !true → false
// Шаг 2: !false → true
// Итоговый результат: true
Как объясняется в блоге SourceBae, унарный оператор ! преобразует свой операнд в Булево значение и инвертирует его. Этот факт приводит к тому, что шаблон двойного восклицательного знака эквивалентен поведению функции Boolean().
Ключевое понимание заключается в том, что оператор !! по сути снимает исходный тип значения и возвращает чистое булево представление о том, является ли значение “истинным” (truthy) или “ложным” (falsy) в JavaScript.
Истинные и ложные значения
В JavaScript существуют определенные правила для того, какие значения считаются “ложными” (преобразуются в false) и “истинными” (преобразуются в true):
Ложные значения (Falsy)
false- булево значение falsenull- отсутствие любого значенияundefined- переменная, объявленная, но не присвоенная значение0- число ноль-0- отрицательный нольNaN- Not-a-Number (не число)""- пустая строка
Все остальные значения в JavaScript считаются истинными (truthy), включая:
- Непустые строки
- Ненулевые числа
- Объекты (включая массивы и функции)
- Даты
- Любое другое не-null, не-undefined значение
Как показано в объяснении от DEV Community, можно увидеть, как ведут себя разные значения:
// Ложные значения
console.log(!!null) // false
console.log(!!0) // false
console.log(!!undefined) // false
console.log(!!"") // false
console.log(!!NaN) // false
// Истинные значения
console.log(!!"dwd") // true
console.log(!!5) // true
console.log(!![]) // true
console.log(!!{}) // true
Практические примеры
Давайте рассмотрим фрагмент кода из вашего вопроса:
this.vertical = vertical !== undefined ? !!vertical : this.vertical;
Вот что происходит с этим кодом:
- Сначала проверяется, не равно ли
verticalundefined - Если true, применяется оператор !! для преобразования
verticalв булево значение - Если false (vertical равен undefined), сохраняется текущее значение
this.vertical
Этот шаблон гарантирует, что бы ни содержало значение vertical, оно преобразуется в правильное булево значение перед присваиванием.
Примеры сценариев:
// Когда vertical - число
let vertical = 42;
this.vertical = vertical !== undefined ? !!vertical : this.vertical;
// !!42 преобразуется в true
// this.vertical становится true
// Когда vertical - пустая строка
let vertical = "";
this.vertical = vertical !== undefined ? !!vertical : this.vertical;
// !!"" преобразуется в false
// this.vertical становится false
// Когда vertical - null
let vertical = null;
this.vertical = vertical !== undefined ? !!vertical : this.vertical;
// !!null преобразуется в false
// this.vertical становится false
// Когда vertical - undefined
let vertical = undefined;
this.vertical = vertical !== undefined ? !!vertical : this.vertical;
// Условие ложно, поэтому this.vertical остается без изменений
Сравнение с функцией Boolean()
Оператор !! функционально эквивалентен конструкторской функции Boolean(), но между ними есть некоторые различия:
// Оба способа дают одинаковый результат
!!"hello" === Boolean("hello") // true
!!0 === Boolean(0) // true
!!null === Boolean(null) // true
!!undefined === Boolean(undefined) // true
Однако есть некоторые тонкие различия:
Производительность
Оператор !! обычно быстрее, чем Boolean(), потому что это простая побитовая операция, в то время как Boolean() включает накладные расходы на вызов функции.
Поведение преобразования типов
Оба метода обрабатывают один и тот же набор значений одинаково, но Boolean() иногда может вести себя по-разному при вызове с объектами.
Читаемость
!!valueболее лаконичен и распространен в современном JavaScript кодеBoolean(value)более явный и самодокументируемый- Некоторые разработчики находят !! запутанным, в то время как другие ценят его краткость
Согласно GitHub gist, сравнивающему два подхода, оба метода достигают одного и того же результата преобразования булевого типа.
Распространенные случаи использования
Оператор двойного восклицательного знака commonly используется в нескольких сценариях:
1. Явное преобразование в булев тип
Когда вам нужно убедиться, что значение обрабатывается как булево в условных выражениях:
function isValid(user) {
return !!user && !!user.name && !!user.email;
}
2. Возвращаемые значения функций
Когда функции нужно возвращать последовательные булевы значения:
function hasPermission(permissions, requiredPermission) {
return !!permissions && permissions.includes(requiredPermission);
}
3. Проверка существования свойств
Как упоминалось в вашем примере, он полезен для проверки существования свойств и их преобразования в булевы значения:
const config = {
enabled: true,
debug: false,
logging: undefined
};
// Преобразование всех значений конфигурации в булевы
const booleanConfig = {
enabled: !!config.enabled, // true
debug: !!config.debug, // false
logging: !!config.logging // false
};
4. Проверки массивов/объектов
При работе с коллекциями и необходимости проверить, содержат ли они элементы:
const items = [];
const hasItems = !!items.length; // false
const users = [{name: "John"}];
const hasUsers = !!users.length; // true
Вопросы производительности
Оператор двойного восклицательного знака обычно очень производителен в JavaScript:
Скорость
Оператор !! — это простая побитовая операция, оптимизированная JavaScript-движками. Он обычно превосходит Boolean() по производительности из-за отсутствия накладных расходов на вызов функции.
Когда использовать
- Используйте !!, когда производительность критична и вам нужно быстрое преобразование в булев тип
- Используйте Boolean(), когда читаемость кода важнее микрооптимизаций
- Учитывайте контекст - в большинстве приложений разница незначительна
Заметная разница в производительности
Как отмечено в различных источниках, разница в производительности между !! и Boolean() обычно заметна только в критически важном для производительности коде или когда операция выполняется миллионы раз.
Заключение
Оператор двойного восклицательного знака (!!) — это мощный и лаконичный способ преобразовать любое значение JavaScript в его булев эквивалент. Применяя оператор логического НЕ дважды, он эффективно снимает исходный тип значения и возвращает true или false на основе правил JavaScript для истинных и ложных значений. Этот оператор особенно полезен в сценариях, где требуются явные булевы значения, как в вашем примере кода, который обеспечивает последовательное присваивание булевого типа. Хотя функционально эквивалентен конструктору Boolean(), оператор !! предлагает лучшую производительность и широко используется в современном JavaScript-разработке благодаря своей краткости и эффективности.
Источники
- Как работает двойное восклицание (!!) в JavaScript? - Stack Overflow
- Что означает двойное восклицание в JavaScript? - Medium
- Двойные восклицательные знаки в JavaScript 🧐 - Medium
- Объяснение двойного восклицательного знака в JavaScript (с примерами) - DEV Community
- Что означает двойное восклицание в JavaScript? - Brian Love
- Что делает оператор двойного восклицательного знака в JavaScript? - Stack Overflow
- Что делает оператор двойного восклицательного знака в JavaScript? - SourceBae
- Оператор двойного восклицания (!!) в JavaScript - codingem.com
- Очистка вашего JavaScript: Двойной банг (!!) - John Kavanagh
- JavaScript | Как работают двойные восклицательные знаки (!!) - Become A Better Programmer