为什么在if语句中使用双感叹号?

时间:2018-09-07 22:54:24

标签: javascript if-statement

我最近阅读了一些代码,这些代码使用!!将变量转换为布尔值,以便在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...");
}

4 个答案:

答案 0 :(得分:5)

简短答案:不,没有理由。

在您的代码中,它已经是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);

答案 1 :(得分:2)

我想说这主要是为了提高代码的可读性。我怀疑是否会对性能或兼容性产生重大影响(请随时进行测试)

但是在代码可读性方面,这向我暗示此变量以前不是布尔值,但是如果要添加有关此变量的新逻辑,请记住这一点。

>

尽管在您的情况下,它已经是布尔值,所以它是100%冗余的,但是我猜只是出于某种原因,有人过度使用了上面的推理,并且/或者在其他地方看到它并复制该模式而没有完全理解它(一个简短的习惯)故事时间:在C#中,您可以通过添加@将受保护的术语命名为变量名称,因此var @class = "hello";是一个初级开发者,只是假定 all 需要变量名@我想知道是否有人假设没有比较运算符的if是否需要在!!之前作为比较运算符

答案 2 :(得分:1)

在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"

我想这是一种由于上述用例而习惯的习惯,因此在希望解决变量的真实性时总是转换为布尔值。对于我们(人类和程序员)而言,始终遵循一条规则比较容易。即使在周围没人的情况下,您也可以一直在车上使用方向指示灯,或者您可能偶尔(或经常)忘记发信号告知何时应该拥有。

答案 3 :(得分:1)

这完全取决于atTop变量的值。遵循讨论here

总而言之,如果atTop的值与boolean有所不同,则第一个否定会将其转换为布尔值(取反)。第二次求反将使布尔值返回到原始atTop值的等效布尔值。

例如,如果atTopundefined,则第一个!将其变为boolean true,然后第二个!将其变为{{1} }(相当于boolean false的布尔值)

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