Что означает два восклицательных знака "!!" перед выражением?
Что означает, когда пишут два восклицательных знака перед переменной или любым другим выражением? Например:
const isTrue = (content) => {
return !!content;
};
Прежде всего давайте вспомним что вообще делает восклицательный знак в обычных ситуациях. Он является логическим оператором "не". Простой пример, проверяем что выражения между собой равны:
console.log('test' === 'test'); // => true
Если хотим проверить что они не равны, то добавляем восклицательный знак:
console.log('test' !== 'test'); // => false
То есть мы "перевернули" (инвертировали) проверку. Примерно то же самое происходит, когда мы добавляем восклицательный знак перед любым выражением:
const myVar = 'test';
console.log(!myVar); // => false
Обратите внимание, перед myVar
стоит восклицательный знак, это отрицание, то есть можно прочитать это как "не myVar". Восклицательный знак инвертирует наше выражение, которое является строкой 'test'. Но тут возникает вопрос: а что является не строкой 'test'? Если подойти к вопросу философски, то можно найти бесконечное множество вещей, которые являются не строкой 'test'. Но у интерпретатора JS на этот счёт есть чёткое правило: он вычисляет выражение справа от восклицательного знака так, чтобы получить либо true
, либо false
, то есть приводит к булевому типу. Строка 'test' приводится к булевому типу и вычисляется как true
, а восклицательный знак инвертирует, то есть переворачивает true
на false
, так как false
является противоположностью true
.
Теперь гораздо легче понять что делают два восклицательных знака:
const isTrue = (content) => {
return !!content;
};
Интерпретатор пытается вычислить сначала !content
. Если content
будет ложным выражением, то вычислится true
, если истинным, то false
. А второй восклицательный знак переворачивает true
на false
, а false
на true
. В итоге, если контент существует, то функция вернёт true
, а если не существует, то false
.
Теперь возникает вопрос: зачем вообще это нужно? Это делается чтобы мы всегда работали с определённым типом. Такой хитрый способ позволяет нам добиться чтобы функция всегда возвращала булевый тип. Любое значение будет преобразовываться в этот булевый тип. Это называется приведение типов.
Еще можно добавить, что в javascript следующие значения будут приведены к булевому типу false:
- undefined
- null
- NaN
- 0 (число ноль)
- '' (пустая строка)
В английской литературе эти значения называются falsy values.
[undefined, null, NaN, 0, ''].map((val) => !!val);
// => [ false, false, false, false, false ]
// или можно так: [undefined, null, NaN, 0, ''].map((val) => Boolean(val))