我看到一些代码似乎使用了我不认识的运算符,以两个感叹号的形式,像这样:!!。有人能告诉我这个接线员做什么吗?
我看到这件事的背景是,
this.vertical = vertical !== undefined ? !!vertical : this.vertical;
我看到一些代码似乎使用了我不认识的运算符,以两个感叹号的形式,像这样:!!。有人能告诉我这个接线员做什么吗?
我看到这件事的背景是,
this.vertical = vertical !== undefined ? !!vertical : this.vertical;
当前回答
这里有很多很棒的答案,但如果你读到这里,这帮助我“找到答案”。在Chrome(等)中打开控制台,然后开始键入:
!(!(1))
!(!(0))
!(!('truthy'))
!(!(null))
!(!(''))
!(!(undefined))
!(!(new Object())
!(!({}))
woo = 'hoo'
!(!(woo))
...etc., etc., until the light goes on ;)
当然,这些都和仅仅打字一样!!但添加的括号可能有助于使其更易于理解。
其他回答
const foo=“bar”;console.log(!!foo);//布尔值:真
! 对值求反(反转),并始终返回/生成布尔值。所以!”bar'将产生false(因为'bar'是truthy=>否定+布尔值=false)。附加的!运算符,该值再次被求反,因此false变为true。
!! 只是两次NOT运算符。净效果就是转换任何东西以确保布尔数据类型。例如
!!undefined为false!!0为假!!null为false!!anyobject为true!!真是真!!false是false!0为真!1为假!!'' 是假的
要将JavaScript变量转换为布尔值,
var firstname = "test";
// Type of firstname is string
var firstNameNotEmpty = !!firstname;
// Type of firstNameNotEmpty is Boolean
JavaScript false表示“”、0、undefined和null。
JavaScript对于除零以外的数字是真的,而不是空字符串、{}、[]和new Date(),因此,
!!("test") /* Is true */
!!("") /* Is false */
!! 将其右侧的值转换为其等效的布尔值。(想想穷人的“类型转换”方式。)其目的通常是向读者传达,代码不关心变量中的值,而是关心变量的“真值”值。
if和while语句以及?运算符使用真值来确定要运行的代码分支。例如,零和NaN数字以及空字符串为假,但其他数字和字符串为真。对象为true,但未定义的值和null均为false。
双重否定运算符!!计算值的真值。实际上是两个操作员,哪里!!x表示!(!x),并且行为如下:
如果x为假值!x为真,并且!!x为假。如果x是真值!x为假,并且!!x为真。
当在布尔上下文的顶层使用时(if、while或?)!!从行为上讲,操作员是一个no-op。例如,if(x)和if(!!x)表示相同的意思。
实际用途
然而,它有几个实际用途。
一种用法是将对象压缩到其真值,这样代码就不会保存对大对象的引用并保持其活动。分配!!some_big_object设置为变量,而不是some_biguobject让垃圾收集器使用它。这对于生成对象或假值(例如空值或未定义值)的情况非常有用,例如浏览器特征检测。
另一个用法,我在一个关于C对应的答案中提到了!!操作员使用“lint”工具查找常见的打字错误和打印诊断。例如,在C和JavaScript中,布尔运算的一些常见错误会产生其他输出不太布尔的行为:
如果(a=b)是赋值,然后使用b的真值;如果(a==b)是相等比较。如果(a&b)是位AND;如果(a&&b)是逻辑AND。2和5为0(假值);2&&5为真。
这个操作员向lint工具保证,您所写的就是您的意思:执行此操作,然后获取结果的真值。
第三种用途是产生逻辑XOR和逻辑XNOR。在C和JavaScript中,a&b都执行逻辑and(如果两边都为true,则为true),a&b执行逐位and。a||b执行逻辑或(如果至少有一个为真,则为真),a|b执行逐位或。有一个按位XOR(异或)作为^b,但没有用于逻辑XOR的内置运算符(如果只有一侧为真,则为真)。例如,您可能希望允许用户仅在两个字段中的一个字段中输入文本。您可以做的是将每个值转换为一个真值,并将它们进行比较:!!x!==!!y