为啥在 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 类型,无需转换,再次转换回来,您将始终得到相同的结果。实际上,如果您有任何布尔值(truefalse),当您将!! 与其中任何一个一起使用时,它将被转换回它的初始值:

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 值的等效布尔值。

例如,如果atTopundefined,则第一个! 将其转换为boolean true,然后第二个! 将其转换为boolean false(这将是undefined 的等效布尔值)

但是,在您的代码中,atTop 值是严格相等 === 的结果,这意味着您始终会在 atTop 中得到一个布尔值。因此,您不需要将非布尔值转换为布尔值,因此不需要 !!

【讨论】:

以上是关于为啥在 if 语句中使用双感叹号?的主要内容,如果未能解决你的问题,请参考以下文章

php技术–php中感叹号!和双感叹号!!的用法(三元运算)

C语言 if用法

三重感叹号的使用

PHP中函数前的感叹号是啥意思

C语言中双感叹号的作用

Java的方法参数中的双感叹号和#号是啥意思?