НейроАгент

Что делает оператор !! в JavaScript?

Узнайте, как оператор двойного восклицательного знака (!!) преобразует значения JavaScript в булевы. Понимайте истинные/ложные значения, практические примеры и когда использовать эту лаконичную технику преобразования в булев тип.

Вопрос

Что делает оператор двойного восклицательного знака (!!) в JavaScript? Я столкнулся с этим фрагментом кода:

javascript
this.vertical = vertical !== undefined ? !!vertical : this.vertical;

Похоже, что здесь используется !! как оператор, с которым я не знаком. Можете объяснить, что делает этот оператор и как он работает в JavaScript?

НейроАгент

Оператор двойного восклицательного знака (!!) в JavaScript — это сокращенный метод для преобразования любого значения в его булев эквивалент. Он работает путем применения оператора логического НЕ дважды: сначала преобразуя значение в булев тип и инвертируя его, а затем инвертируя результат обратно к исходному булевому значению. Этот оператор commonly используется для обеспечения последовательного булевого при работе со значениями, которые являются истинными (truthy) и ложными (falsy).

Содержание

Понимание оператора двойного восклицательного знака

Оператор двойного восклицательного знака (!!) в JavaScript не является самостоятельным оператором — это на самом деле два последовательных применения оператора логического НЕ (!). Этот часто называют “двойной банг” (double bang) разработчики. Основная цель этого шаблона оператора — преобразовать любое значение JavaScript в его булев эквивалент.

Как объясняется в обсуждении на Stack Overflow, оператор !! по сути является сокращенным методом приведения переменных к булевому значению (true или false). Этот шаблон особенно полезен, когда вам явно нужно работать с булевыми значениями, а не полагаться на оценку JavaScript истинных/ложных значений.

Как работает оператор !!

Оператор двойного восклицательного знака работает через двухэтапный процесс:

  1. Первый оператор !: Преобразует значение в булев тип и инвертирует его
  2. Второй оператор !: Инвертирует результат снова, возвращая исходное булево значение

Давайте разберем это на конкретном примере:

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 - булево значение false
  • null - отсутствие любого значения
  • undefined - переменная, объявленная, но не присвоенная значение
  • 0 - число ноль
  • -0 - отрицательный ноль
  • NaN - Not-a-Number (не число)
  • "" - пустая строка

Все остальные значения в JavaScript считаются истинными (truthy), включая:

  • Непустые строки
  • Ненулевые числа
  • Объекты (включая массивы и функции)
  • Даты
  • Любое другое не-null, не-undefined значение

Как показано в объяснении от DEV Community, можно увидеть, как ведут себя разные значения:

javascript
// Ложные значения
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

Практические примеры

Давайте рассмотрим фрагмент кода из вашего вопроса:

javascript
this.vertical = vertical !== undefined ? !!vertical : this.vertical;

Вот что происходит с этим кодом:

  1. Сначала проверяется, не равно ли vertical undefined
  2. Если true, применяется оператор !! для преобразования vertical в булево значение
  3. Если false (vertical равен undefined), сохраняется текущее значение this.vertical

Этот шаблон гарантирует, что бы ни содержало значение vertical, оно преобразуется в правильное булево значение перед присваиванием.

Примеры сценариев:

javascript
// Когда 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(), но между ними есть некоторые различия:

javascript
// Оба способа дают одинаковый результат
!!"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. Явное преобразование в булев тип

Когда вам нужно убедиться, что значение обрабатывается как булево в условных выражениях:

javascript
function isValid(user) {
    return !!user && !!user.name && !!user.email;
}

2. Возвращаемые значения функций

Когда функции нужно возвращать последовательные булевы значения:

javascript
function hasPermission(permissions, requiredPermission) {
    return !!permissions && permissions.includes(requiredPermission);
}

3. Проверка существования свойств

Как упоминалось в вашем примере, он полезен для проверки существования свойств и их преобразования в булевы значения:

javascript
const config = {
    enabled: true,
    debug: false,
    logging: undefined
};

// Преобразование всех значений конфигурации в булевы
const booleanConfig = {
    enabled: !!config.enabled,    // true
    debug: !!config.debug,        // false
    logging: !!config.logging     // false
};

4. Проверки массивов/объектов

При работе с коллекциями и необходимости проверить, содержат ли они элементы:

javascript
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-разработке благодаря своей краткости и эффективности.

Источники

  1. Как работает двойное восклицание (!!) в JavaScript? - Stack Overflow
  2. Что означает двойное восклицание в JavaScript? - Medium
  3. Двойные восклицательные знаки в JavaScript 🧐 - Medium
  4. Объяснение двойного восклицательного знака в JavaScript (с примерами) - DEV Community
  5. Что означает двойное восклицание в JavaScript? - Brian Love
  6. Что делает оператор двойного восклицательного знака в JavaScript? - Stack Overflow
  7. Что делает оператор двойного восклицательного знака в JavaScript? - SourceBae
  8. Оператор двойного восклицания (!!) в JavaScript - codingem.com
  9. Очистка вашего JavaScript: Двойной банг (!!) - John Kavanagh
  10. JavaScript | Как работают двойные восклицательные знаки (!!) - Become A Better Programmer