为啥在 if 语句中使用双感叹号?
Posted
技术标签:
【中文标题】为啥在 if 语句中使用双感叹号?【英文标题】:Why use double exclamation marks in an if statement?为什么在 if 语句中使用双感叹号? 【发布时间】:2019-02-13 06:38:27 【问题描述】:我最近阅读了一些代码,它使用!!
将变量转换为布尔值,以便在 if 语句中进行评估。这对我来说似乎有些多余,因为无论如何都会评估变量的布尔值。这样做有什么性能优势,还是为了更好的浏览器支持?
示例代码:
var x = 0;
var atTop = x===window.scrollY;
if(!!atTop)
alert("At the top of the page.");
编辑:
对于非布尔类型的操作数,我也看到了这一点,但我一直认为使用 if
无论如何都会评估变量的布尔值,因为 javascript 中的所有值要么是“真”,要么是“假” .
示例代码:
var x = 1;//or any other value including null, undefined, some string, etc
if(!!x)//x is "truthy"
//wouldn't using if(x) be the same???
console.log("something...");
【问题讨论】:
What is the !! (not not) operator in JavaScript?的可能重复 @csmckelvey:不是那个问题的重复。这个问题是:如果操作数已经是布尔值,还有什么理由使用!!
?
@csmckelvey 我知道!!
做了什么(将变量转换为布尔值),但我想问是否有任何理由在 if 语句中使用它。
这样做有什么性能优势还是为了更好的浏览器支持?。两者都不。将虚假/真实值转换为布尔值基本上是一个巧妙的技巧。在您的具体示例中,尽管atTop
已经是一个布尔值,因此无需使用它。
在 if 语句中,没关系。但是当您在节点中准备 JSON 以发送到浏览器时会很有帮助,反之亦然。
【参考方案1】:
简答:不,没有理由。
在您的代码中,它已经是boolean
类型,无需转换,再次转换回来,您将始终得到相同的结果。实际上,如果您有任何布尔值(true
或 false
),当您将!!
与其中任何一个一起使用时,它将被转换回它的初始值:
console.log(!!true); // Will be always "true"
console.log(typeof !!true); // It stills a "boolean" type
console.log(!!false); // Will be always "false"
console.log(typeof !!false); // It stills a "boolean" type
已编辑问题的答案:是的,是一样的。这就是if(...)
实际上所做的——它试图将任何类型转换为boolean
。
这是一个小测试,你可以玩弄它并在initialArr
数组中添加任何你想要的东西来测试,它与if
和!!
的行为是否相同:
const initialArr = [
undefined,
null,
true,
false,
0,
3,
-1,
+Infinity,
-Infinity,
Infinity,
'any',
'',
function() return 1 ,
,
prop: 1 ,
[],
[0],
[0, 1]
];
function testIsTheSame(arr)
equolityCounter = 0;
arr.forEach(item =>
let ifStatement = false;
let doubleNotStatement = !!item;
if(item)
ifStatement = true;
if(ifStatement === doubleNotStatement && typeof ifStatement === typeof doubleNotStatement)
equolityCounter++;
);
console.log(`Is the same: $equolityCounter === arr.length`);
testIsTheSame(initialArr);
【讨论】:
非常感谢您的解释。【参考方案2】:我想说这主要是为了代码可读性。我怀疑是否存在任何显着的性能或兼容性影响(请随意测试)
但在代码可读性方面,这对我来说意味着该变量以前不是布尔值,但我们希望将其评估为一个,如果您添加有关此变量的新逻辑,请记住这一点。
虽然在您的情况下它已经是布尔值,所以它 100% 是多余的,但我猜想只是有人对上述推理的习惯过度应用,和/或在其他地方看到它并在没有完全理解的情况下复制该模式(简短故事时间:在 C# 中,您可以通过添加 @
将受保护的术语命名为变量名称,因此 var @class = "hello";
,初级开发人员只是假设 所有 变量名称需要在它们前面加上 @
,并且以这种方式编码。我想知道是否有人认为没有比较运算符的 if 需要在其前面有 !!
作为比较运算符)
【讨论】:
【参考方案3】:在 if 语句中执行此操作没有任何运行时好处(或客观好处)。 if 语句执行的评估将产生与双感叹号产生的评估完全相同的结果。没有区别。
双感叹号是确保布尔值基于真实性的有用表达。例如,考虑:
var text = undefined;
console.log(text); // undefined
console.log(!!text); // false
// It would make sense here, because a boolean value is expected.
var isTextDefined = !!text;
// It would also affect serialization
JSON.stringify(text); // undefined (non-string)
JSON.stringify(!!text); // "false"
我想这是由于上述用例而养成的习惯,因此在希望解决变量的真实性时总是转换为布尔值。对我们(人类和程序员)来说,当它总是被应用时,它更容易遵循它。您要么一直使用车内的信号灯,即使周围没有人,也可能偶尔(或可能经常)忘记在应该使用信号灯时发出信号。
【讨论】:
【参考方案4】:这完全取决于atTop
变量的值。关注here的讨论。
总而言之,如果atTop
的值与boolean
不同,则第一个否定会将其转换为布尔值(否定)。第二次否定会将布尔值返回为原始atTop
值的等效布尔值。
例如,如果atTop
是undefined
,则第一个!
将其转换为boolean true
,然后第二个!
将其转换为boolean false
(这将是undefined
的等效布尔值)
但是,在您的代码中,atTop
值是严格相等 ===
的结果,这意味着您始终会在 atTop
中得到一个布尔值。因此,您不需要将非布尔值转换为布尔值,因此不需要 !!
。
【讨论】:
以上是关于为啥在 if 语句中使用双感叹号?的主要内容,如果未能解决你的问题,请参考以下文章