是什么 !!(不是)JavaScript中的运算符?

2020/09/14 01:01 · javascript ·  · 0评论

我看到了一些似乎使用我不认识的运算符的代码,它以两个感叹号的形式出现,如下所示:!!有人可以告诉我这个操作员做什么吗?

我看到的背景是

this.vertical = vertical !== undefined ? !!vertical : this.vertical;

转换Objectboolean如果是falsey(例如0nullundefined等),这将是false,否则,true

!oObject  // inverted boolean
!!oObject // non inverted boolean so true boolean representation

所以!!不是运算符,只是!运算符的两倍。

真实示例“测试IE版本”:

const isIE8 = !! navigator.userAgent.match(/MSIE 8.0/);  
console.log(isIE8); // returns true or false 

如果你⇒

console.log(navigator.userAgent.match(/MSIE 8.0/));  
// returns either an Array or null  

但是如果你⇒

console.log(!!navigator.userAgent.match(/MSIE 8.0/));  
// returns either true or false

这是进行类型转换的令人费解的方法。

!不是所以!truefalse!falsetrue!0true!1false

因此,您要将一个值转换为布尔值,然后将其求反,然后再次将其求反。

// Maximum Obscurity:
val.enabled = !!userId;

// Partial Obscurity:
val.enabled = (userId != 0) ? true : false;

// And finally, much easier to understand:
val.enabled = (userId != 0);

!!expr根据表达式真实性返回布尔值(truefalse在非布尔类型上使用时更有意义。考虑以下示例,尤其是第三个示例及以后的示例:

          !!false === false
           !!true === true

              !!0 === false
!!parseInt("foo") === false // NaN is falsy
              !!1 === true
             !!-1 === true  // -1 is truthy
          !!(1/0) === true  // Infinity is truthy

             !!"" === false // empty string is falsy
          !!"foo" === true  // non-empty string is truthy
        !!"false" === true  // ...even if it contains a falsy value

     !!window.foo === false // undefined is falsy
           !!null === false // null is falsy

             !!{} === true  // an (empty) object is truthy
             !![] === true  // an (empty) array is truthy; PHP programmers beware!

冲泡一些茶:

!!不是运算符。它是-的双重用途,!它是逻辑上的“非”运算符。


理论上:

! 确定值不是什么的“真相”:

  • 事实false并非如此true(这就是!false导致的原因true

  • 事实true并非如此false(这就是!true导致的原因false


!!确定不是值的“真相”

  • 事实是true并非如此 true(这就是!!true导致的原因true

  • 事实是false并非如此 false(这就是!!false导致的原因false


我们希望在比较中确定的是关于参考值的“真实性” ,而不是参考本身在一个用例中,即使我们期望值是false(或错误的),或者期望值不是typeof ,我们也可能想知道关于值的真相boolean


在实践中:

考虑一个简洁的功能,该功能通过动态类型(也称为“鸭子类型”)检测功能(在这种情况下为平台兼容性)。我们想要编写一个函数,true如果用户的浏览器支持HTML5 <audio>元素,该函数返回,但是如果<audio>函数未定义,我们不希望该函数抛出错误并且我们不想用来try ... catch处理任何可能的错误(因为它们很严重);而且我们也不想在函数内部使用不会始终揭示该功能真相的检查(例如,即使不支持HTML5 ,它document.createElement('audio')仍会创建一个名为的元素)。<audio><audio>


这是三种方法:

// this won't tell us anything about HTML5 `<audio>` as a feature
var foo = function(tag, atr) { return document.createElement(tag)[atr]; }

// this won't return true if the feature is detected (although it works just fine)
var bar = function(tag, atr) { return !document.createElement(tag)[atr]; }

// this is the concise, feature-detecting solution we want
var baz = function(tag, atr) { return !!document.createElement(tag)[atr]; }

foo('audio', 'preload'); // returns "auto"
bar('audio', 'preload'); // returns false
baz('audio', 'preload'); // returns true

每个函数都接受a <tag>和an attribute要查找的参数,但是它们各自根据比较确定的结果返回不同的值。

但是,等等,还有更多!

你们中的某些人可能已经注意到,在此特定示例中,可以使用性能稍强的一种方法来检查相关对象是否具有属性,从而简单地检查属性。有两种方法可以做到这一点:

// the native `hasOwnProperty` method
var qux = function(tag, atr) { return document.createElement(tag).hasOwnProperty(atr); }

// the `in` operator
var quux = function(tag, atr) { return atr in document.createElement(tag); }

qux('audio', 'preload');  // returns true
quux('audio', 'preload'); // returns true

我们离题了...

不管这些情况多么罕见,在某些情况下,最简洁,最高效,因此最优选的true从非布尔值,可能未定义的值中获取的方法的确是使用!!希望这很荒谬。

!!将其右侧的值转换为其等效的布尔值。(想想穷人的“类型转换”方式)。它的意图是通常传达给读者,代码并不关心什么值是可变的,但它的“真”值是。

!!foo将两次unary not运算符应用两次,并用于将其转换为布尔类型,类似于使用unary plus +foo将其转换为数字并连接一个空字符串''+foo以转换为字符串。

除了这些技巧外,您还可以使用与原始类型相对应的构造函数(使用new)来显式转换值,即

Boolean(foo) === !!foo
Number(foo)  === +foo
String(foo)  === ''+foo

这么多的答案完成了一半的工作。是的,!!X可以理解为“ X(表示为布尔值)的真实性”。但是!!,实际上,对于弄清单个变量是真实的还是虚假的,并不是那么重要。!!myVar === true与正义一样myVar!!X“真实”布尔值进行比较并没有真正的用处。

您将获得以可重复,标准化(和JSLint友好)的方式相互!!检查多个变量的真实性的能力

简单地铸造:(

那是...

  • 0 === falsefalse
  • !!0 === falsetrue

以上不是那么有用。if (!0)给您与相同的结果if (!!0 === false)我想不出将变量转换为布尔值然后与“ true”布尔值进行比较的好例子。

请从JSLint的指导中查看“ ==和!=“ (注意:Crockford 会将其站点稍微移动一下;该链接可能会在某个时间点消失),其中有一些原因:

==和!=运算符在比较之前会键入强制。这很糟糕,因为它导致'\ t \ r \ n'== 0为真。这可以掩盖类型错误。JSLint无法可靠地确定==是否正确使用,因此最好不要使用==和!=,而始终使用更可靠的===和!==运算符。

如果您只关心值是真实的还是虚假的,请使用缩写形式。代替
(foo != 0)

说啊
(foo)

而不是
(foo == 0)


(!foo)

请注意,有一些直观的情况下,其中一个布尔值将被转换为数值(true强制转换1false0比较一个布尔值的号码时)。在这种情况下,!!可能对心理有用。同样,在这些情况下,您正在将非布尔值与硬类型的布尔值进行比较,这是一个严重的错误。 if (-1)仍然是这里的路。

╔═══════════════════════════════════════╦═══════════════════╦═══════════╗
               Original                    Equivalent       Result   
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
 if (-1 == true) console.log("spam")    if (-1 == 1)       undefined 
 if (-1 == false) console.log("spam")   if (-1 == 0)       undefined 
   Order doesn't matter...                                           
 if (true == -1) console.log("spam")    if (1 == -1)       undefined 
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
 if (!!-1 == true) console.log("spam")  if (true == true)  spam       better
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
 if (-1) console.log("spam")            if (truthy)        spam       still best
╚═══════════════════════════════════════╩═══════════════════╩═══════════╝

而且取决于您的引擎,事情变得更加疯狂。以WScript为例。

function test()
{
    return (1 === 1);
}
WScript.echo(test());

由于Windows一些历史记录,它将在消息框中输出-1!在cmd.exe提示中尝试一下,看看吧!WScript.echo(-1 == test())仍然给您0或WScript的false别看 太可怕了

比较真实性:)

但是,如果我有两个值需要检查相等的真实性/虚假性,该怎么办?

假装我们有myVar1 = 0;myVar2 = undefined;

  • myVar1 === myVar20 === undefined而且显然是错误的。
  • !!myVar1 === !!myVar2!!0 === !!undefined,是真的!同样的真实性!(在这种情况下,两个“都具有虚假的真实性”。)

因此,您真正需要使用“布尔值转换的变量”的唯一地方是,如果您要检查两个变量是否具有相同的真实性,对吗?也就是说,使用!!,如果你需要查看两个瓦尔是既truthy或两者falsy(或没有),也就是相等(或没有)感实性

我无法想到一个出色的,非人为的用例。也许您具有表单中的“链接”字段?

if (!!customerInput.spouseName !== !!customerInput.spouseAge ) {
    errorObjects.spouse = "Please either enter a valid name AND age " 
        + "for your spouse or leave all spouse fields blank.";
}

因此,现在,如果您对配偶双方的姓名或年龄均不真实,或者对配偶姓名和年龄均不真实,则可以继续。否则,您只有一个带有值的字段(或者很早就安排了婚姻),并且需要在errorObjects集合上创建一个额外的错误


编辑2017年10月24日,19年2月6日:

期望显式布尔值的第三方库

这是一个有趣的情况…… !!当第三方库期望显式布尔值时可能会有用。

例如,JSX(React)中的False具有特殊含义,不会因简单的虚假行为而触发。如果您尝试在JSX中返回类似以下内容的内容,则期望int messageCount...

{messageCount && <div>You have messages!</div>}

...当您收到0零条消息时,看到React渲染一个可能会让您感到惊讶您必须明确地返回false,JSX才能不呈现。上面的语句返回0,这是JSX乐意呈现的。它不能告诉您没有Count: {messageCount && <div>Get your count to zero!</div>}(或其他较不人为的东西)。

  • 一种解决方法是将bangbang强制0转换为!!0,即false
    {!!messageCount && <div>You have messages!</div>}

  • JSX的文档建议您更加明确,编写自我注释的代码,并使用比较来强制使用布尔值。
    {messageCount > 0 && <div>You have messages!</div>}

  • 我更愿意用三元来处理虚假行为-
    {messageCount ? <div>You have messages!</div> : false}

在Typescript中也是如此:如果您有一个返回布尔值的函数(或者您正在为布尔变量赋值),则[通常]您将无法返回/分配布尔y值;它必须是一个强类型的布尔值。这意味着,iff myObject是强类型的return !myObject;适用于返回布尔值的函数,但return myObject;不能返回布尔值您必须return !!myObject符合Typescript的期望。

Typescript例外?如果myObjectany,则返回JavaScript的Wild West !!,即使返回类型为布尔值,也可以不带返回。

请记住,这些是JSX和Typescript约定,而不是JavaScript固有的约定

但是,如果0在渲染的JSX中看到奇怪的,请考虑宽松的虚假管理。

它只是逻辑非运算符,两次-用于将某些内容转换为布尔值,例如:

true === !!10

false === !!0

它将后缀转换为布尔值。

这是双重not操作。第一个!将值转换为布尔值,然后将其逻辑值反转。第二个!将逻辑值反向。

似乎!!运算符导致双重否定。

var foo = "Hello World!";

!foo // Result: false
!!foo // Result: true

它模拟了Boolean()强制转换功能的行为NOT无论给定什么操作数,第一个都返回布尔值。第二个取反NOTBoolean值,因此给出true变量布尔值。最终结果与Boolean()在值上使用函数相同

是“ boolean not”,实际上是将“ enable”的值转换为与其相反的布尔值。第二 !翻转此值。因此,!!enable意味着“不启用”,为您enable提供布尔值。

我认为值得一提的是,结合了逻辑AND / OR的条件将不会返回布尔值,但在&&的情况下,最后一次成功或第一次失败,而在||的情况下,第一次成功或最后一次失败 条件链。

res = (1 && 2); // res is 2
res = (true && alert) // res is function alert()
res = ('foo' || alert) // res is 'foo'

为了将条件转换为真正的布尔文字,我们可以使用双重否定:

res = !!(1 && 2); // res is true
res = !!(true && alert) // res is true
res = !!('foo' || alert) // res is true

!!它使用NOT两次运算,!将值转换为a boolean并将其反转,这是一个简单的示例,了解其!!工作原理:

首先,您拥有的地方:

var zero = 0;

然后!0,将其转换为boolean并被评估为true,因为0为falsy,所以您获得了相反的值并转换为boolean,因此其被评估为true

!zero; //true

但我们不希望值的布尔取反,因此我们可以再次将其取反以获得结果!这就是为什么我们使用另一个!

基本上,请!!确保我们得到的值是布尔值,而不是虚假,真实或字符串等。

因此,就像Boolean在javascript中使用function 一样,但是将值转换为boolean的简便快捷方式:

var zero = 0;
!!zero; //false

!!构造是将任何JavaScript表达式转换为其等效布尔值的简单方法。

例如:!!"he shot me down" === true!!0 === false

它不是一个运算符,而是两个。它等效于以下内容,是将值强制转换为布尔值的快速方法。

val.enabled = !(!enable);

我怀疑这是C ++的残over剩饭,在这里人们会改写!运算符,但不是布尔运算符。

因此,在这种情况下要获得否定(或肯定)答案,您首先需要使用!运算符以获取布尔值,但是如果要检查肯定的情况,则可以使用!!。

ifwhile报表,?操作者使用真值来确定的代码分支运行。例如,零和NaN数字和空字符串为false,但其他数字和字符串为true。对象为true,但未定义的值null都为false。

双重否定运算符!!计算值的真值。实际上是两个运算符,其中!!xmeans是!(!x),其行为如下:

  • If x是一个错误值,!xis true!!xis false
  • If x是一个真值,!xis false!!xis true

当在布尔上下文的顶层中使用(ifwhile,或?),所述!!操作者是行为上无操作。例如,if (x)if (!!x)意思相同。

实际用途

但是,它有一些实际用途。

一种用途是将对象有损地压缩到其真实值,这样您的代码就不会保留对大对象的引用并使它保持活动状态。分配!!some_big_object给变量而不是some_big_object为垃圾收集器释放它。这对于产生对象或错误值(例如null或未定义值)(例如浏览器功能检测)的情况很有用

我在有关C的相应!!运算符答案中提到的另一种用法是使用“毛绒”工具,这些工具可以查找常见的错字和打印诊断信息。例如,在C和JavaScript中,布尔运算的一些常见错别字会产生其他行为,其输出与布尔值不太相同:

  • if (a = b)是赋值之后是使用的真值b; if (a == b)是一个平等比较。
  • if (a & b)是按位与;if (a && b)是逻辑AND。2 & 50(错误值);2 && 5是真的。

!!运营商再次向皮棉工具,你写的是你的意思:当前操作,然后取结果的真值。

第三种用途是产生逻辑XOR和逻辑XNOR。在C和JavaScript中,都a && b执行逻辑AND(如果双方均为true,则为true),然后a & b执行按位AND。a || b执行逻辑或(如果至少一个为true,则为true),然后a | b执行按位OR。有一个按位的XOR(异或)a ^ b,但没有用于逻辑XOR的内置运算符(如果恰好一侧为true,则为true)。例如,您可能希望允许用户在两​​个字段之一中恰好输入文本。您可以做的是将每个转换为真实值并进行比较:!!x !== !!y

双重布尔取反。通常用于检查值是否未定义。

它将所有事物强制为布尔值。

例如:

console.log(undefined); // -> undefined
console.log(!undefined); // -> true
console.log(!!undefined); // -> false

console.log('abc'); // -> abc
console.log(!'abc'); // -> false
console.log(!!'abc'); // -> true

console.log(0 === false); // -> undefined
console.log(!0 === false); // -> false
console.log(!!0 === false); // -> true

这个问题已经得到了很彻底的回答,但是我想补充一个我希望尽可能简化的答案,使之具有!!的含义!尽可能简单地掌握。

因为javascript具有所谓的“真值”和“假值”,所以有些表达式在其他表达式中求值时会导致为真或假条件,即使所检查的值或表达式实际上不是truefalse

例如:

if (document.getElementById('myElement')) {
    // code block
}

如果该元素确实存在,则表达式的计算结果为true,并将执行代码块。

然而:

if (document.getElementById('myElement') == true) {
    // code block
}

...将不会导致真正的情况,并且即使元素确实存在,也不会执行代码块。

为什么?因为document.getElementById()是一个“真实的”表达式,该表达式在此if()语句中的值为true ,但不是的实际布尔值true

在这种情况下,双“ not”非常简单。not背对背仅两个秒。

第一个简单地“反转”真实值或falsey值,从而产生实际的布尔类型,然后第二个简单地将其“反转”回到其原始状态,但现在变为实际的布尔值。这样,您就可以保持一致性:

if (!!document.getElementById('myElement')) {}

if (!!document.getElementById('myElement') == true) {}

都将按预期返回true。

这里有很多不错的答案,但是,如果您已经读了那么远,这有助于我“了解”。在Chrome(等)上打开控制台,然后开始输入:

!(!(1))
!(!(0))
!(!('truthy')) 
!(!(null))
!(!(''))
!(!(undefined))
!(!(new Object())
!(!({}))
woo = 'hoo'
!(!(woo))
...etc, etc, until the light goes on ;)

当然,这些都与仅键入!! someThing相同,但是添加的括号可能有助于使其更易于理解。

!!x 是的简写 Boolean(x)

第一次爆炸会迫使js引擎运行,Boolean(x)但也会产生反转值的副作用。因此,第二次爆炸消除了副作用。

我只是想补充一点

if(variableThing){
  // do something
}

是相同的

if(!!variableThing){
  // do something
}

但这在未定义内容时可能会成为问题。

// a === undefined, b is an empty object (eg. b.asdf === undefined)
var a, b = {};

// Both of these give error a.foo is not defined etc.
// you'd see the same behavior for !!a.foo and !!b.foo.bar

a.foo 
b.foo.bar

// This works -- these return undefined

a && a.foo
b.foo && b.foo.bar
b && b.foo && b.foo.bar

这里的窍门是&&s 将返回它找到的第一个虚假值 -并且可以将其馈送到if语句等。因此,如果b.foo是未定义的,它将返回undefined并跳过该b.foo.bar语句,而我们没有得到错误。

上面的返回值是undefined,但是如果您有一个空字符串,false,null,0,undefined,则这些值将返回,并且一旦在链中遇到它们[]{}它们都是“真实的”,我们将继续沿所谓的“ &&链接”到右边的下一个值。

PS做同一件事的另一种方法是(b || {}).foo,因为如果b未定义,那么b || {}它将是{},并且您将访问空对象中的值(无错误),而不是尝试访问“ undefined”中的值(导致错误) )。因此,(b || {}).foob && b.foo((b || {}).foo || {}).bar相同b && b.foo && b.foo.bar

看到所有这些很棒的答案之后,我想补充说明使用的另一个原因 !!当前,我正在使用Angular 2-4(TypeScript),并且我想false在用户未通过身份验证时返回一个布尔值如果未通过身份验证,则令牌字符串将为null""我可以通过使用下面的代码块来做到这一点:

public isAuthenticated(): boolean {
   return !!this.getToken();
}

这是来自angular js的一段代码

var requestAnimationFrame = $window.requestAnimationFrame ||
                                $window.webkitRequestAnimationFrame ||
                                $window.mozRequestAnimationFrame;

 var rafSupported = !!requestAnimationFrame;

他们的目的是根据requestAnimationFrame中函数的可用性将rafSupported设置为true或false

通常可以通过以下方式进行检查:

if(typeof  requestAnimationFrame === 'function')
rafSupported =true;
else
rafSupported =false;

简短的方法可能是使用!

rafSupported = !!requestAnimationFrame ;

因此,如果为requestAnimationFrame分配了一个函数,则!requestAnimationFrame将为false!这是真的

如果requestAnimationFrame的值未定义,则!requestAnimationFrame为true,还有一个!这将是错误的

JavaScript中的某些运算符执行隐式类型转换,有时用于类型转换。

一元运算!符将其操作数转换为布尔值并取反。

这个事实导致您可以在源代码中看到以下惯用法:

!!x // Same as Boolean(x). Note double exclamation mark

两次使用逻辑非运算符
意味着!true = false

和!! true = true

返回变量的布尔值。

而是Boolean可以使用class。

(请阅读代码说明)

var X = "test"; // X value is "test" as a String value
var booleanX = !!X // booleanX is `true` as a Boolean value beacuse non-empty strings evaluates as `true` in boolean
var whatIsXValueInBoolean = Boolean(X) // whatIsXValueInBoolean is `true` again
console.log(Boolean(X) === !!X) // writes `true`

Boolean(X) = !!X在使用中。

请检查下面的代码片段

let a = 0
console.log("a: ", a) // writes a value in its kind
console.log("!a: ", !a) // writes '0 is NOT true in boolean' value as boolean - So that's true.In boolean 0 means false and 1 means true.
console.log("!!a: ", !!a) // writes 0 value in boolean. 0 means false.
console.log("Boolean(a): ", Boolean(a)) // equals to `!!a`
console.log("\n") // newline

a = 1
console.log("a: ", a)
console.log("!a: ", !a)
console.log("!!a: ", !!a) // writes 1 value in boolean
console.log("\n") // newline

a = ""
console.log("a: ", a)
console.log("!a: ", !a) // writes '"" is NOT true in boolean' value as boolean - So that's true.In boolean empty strings, null and undefined values mean false and if there is a string it means true.
console.log("!!a: ", !!a) // writes "" value in boolean
console.log("\n") // newline

a = "test"
console.log("a: ", a) // writes a value in its kind
console.log("!a: ", !a)
console.log("!!a: ", !!a) // writes "test" value in boolean

console.log("Boolean(a) === !!a: ", Boolean(a) === !!a) // writes true
本文地址:http://javascript.askforanswer.com/shishenme-bushijavascriptzhongdeyunsuanfu.html
文章标签: ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!