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

问题描述:

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

我看到这个的背景是,

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

解决方案1:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

将 Object 转换为 boolean。如果它是假的(例如 0、null、undefined 等),则为 false,否则为 true。

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

所以 !! 不是运算符,它只是 ! 运算符两次。

这样做可能更简单:

Boolean(object) // boolean

真实世界示例“测试 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

它将非布尔值转换为反转布尔值(例如,!5 为假,因为 5 在 JS 中是非假值),然后布尔反转,因此您将原始值作为布尔值(所以 !!5 将是真的)。

一个简单的描述方法是: Boolean(5) === !!5;相同的演员阵容,更少的角色。

这用于将真值转换为布尔真,而假值太布尔假。

@Micah Snyder 请注意,在 JavaScript 中,最好使用布尔原语,而不是使用 new Boolean() 创建将布尔值框起来的对象。下面是一个示例,可以看出差异:jsfiddle.net/eekbu

据我所知,这种 bang-bang 模式在 if(..._ 语句中没有用;仅在应该返回布尔值的函数的 return 语句中。

解决方案2:

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

这是进行类型转换的一种非常晦涩的方法。

! 表示不。所以 !true 是 false,而 !false 是 true。 !0 是 true,!1 是 false。

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

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

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

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

// Or just
val.enabled = Boolean(userId);

注意:后两个表达式在某些极端情况(例如,当 userId 为 [] 时)并不完全等同于第一个表达式,因为 {3 } 运算符有效,什么值被认为是 truthy。

!!假=假。 !!真=真

“更容易理解”的变体在这里真的更容易理解吗?对 0 的检查不是对 0 的实际检查,而是对 Javascript 认为等于 0 的有点奇怪的值列表进行检查。userId ? true : false 更清楚地表明正在进行转换并处理 userId 的值可能已经存在的情况明确设置为 undefined

我的大脑没有任何问题将 !!var 解码为 Boolean(var) .. 并且 !! 比其他方法更快(处理指令更少)且更短。

!!false 为假。 false != 0 为真。所以它们不是等价的。 !! 用于将 anything 强制为布尔值。

我知道您在多年前写了这个答案,但为了今天对其进行改进:最容易理解的是说出您的意思:Boolean(x)。我认为您的任何替代方案都不容易理解。更糟糕的是,至少在一种情况下,使用相等运算符 x != 0 会得到与 Boolean(x) 或 !!x 不同的结果:尝试 [] for x。此外,如果您确实喜欢使用等式运算符来获得其“真实性”规则,那么您为什么不使用更明显的 (userId == true) 而不是 (userId != 0) 呢?

解决方案3:

huntsbot.com – 高效赚钱,自由工作

!!expr(两个 ! 运算符后跟一个表达式)根据表达式的 真实性 返回一个布尔值(true 或 false)。在非布尔类型上使用时更有意义。考虑这些示例,尤其是第三个示例及以后的示例:

          !!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 value is falsy
      !!undefined === false // undefined primitive is falsy
           !!null === false // null is falsy

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

值得注意的是:!!new Boolean(false) // true

...但也!!Boolean(false) // false

new Boolean(false) 是一个对象,一个对象是真的,即使它包含一个假值!

明确建议将 !!undefined //false 添加到这个出色的答案中!

@SalmanA 扩展为您的正确注释 !!(new Boolean(false).valueOf()) // false(因为 new Boolean 返回一个 Boolean 对象的实例,这是真实的,而 Boolean(false) 或 Boolean valueOf() 将表达式的值强制为原始布尔值)。

解决方案4:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

泡茶:

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

理论上:

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

事实是假不是真的(这就是为什么!假结果为真)

事实是 true 不是 false(这就是为什么 !true 结果为 false)

!! 确定一个值的“真相”not not:

事实是 true 不是 true (这就是为什么 !!true 结果为 true)

事实是假不是不假(这就是为什么!!假导致假)

我们希望在比较中确定的是关于引用值的“真相”,而不是引用本身的值。有一个用例,我们可能想知道一个值的真相,即使我们期望该值是 false (或错误),或者如果我们期望该值不是boolean 类型。

在实践中:

考虑一个简洁的函数,它通过 dynamic typing(又名“duck typing”)检测特性功能(在本例中为平台兼容性)。如果用户的浏览器支持 HTML5 元素,我们希望编写一个返回 true 的函数,但如果 未定义,我们不希望该函数抛出错误;而且我们不想使用 try … catch 来处理任何可能的错误(因为它们很严重); 而且我们不希望在函数内部使用检查不能始终如一地揭示特性的真相(例如,document.createElement(‘audio’) 仍将创建一个名为 的元素,即使不支持 HTML5 )。

以下是三种方法:

// this won't tell us anything about HTML5 `` 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

每个函数都接受要查找的 和 attribute 的参数,但它们各自根据比较确定的内容返回不同的值。

但是等等,还有更多!

你们中的一些人可能已经注意到,在这个特定的示例中,人们可以简单地使用略为 more performant 的方法来检查所讨论的对象是否具有属性。有两种方法可以做到这一点:

// 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 的方法确实是使用 !!。希望这可笑地清除它。

非常棒的答案,但我看不到 !!构造。由于 if() 语句已经将表达式转换为布尔值,因此将测试函数的返回值显式转换为布尔值是多余的 - 因为无论如何“真实性” === true 就 if() 语句而言。还是我错过了一个你需要一个真实的表达式才能真正成为布尔 true 的场景?

@TomAuger if() 语句确实针对虚假值强制转换布尔值,但是说您想在对象上实际设置一个布尔标志 - 它不会像 if() 语句那样强制转换它。例如 object.hasTheThing = !!castTheReturnValToBoolNoMatterWhat() 将设置 true 或 false 而不是真正的返回值。另一个示例可能是所有管理员都是 0 的 id,而非管理员的 id 为 1 或更高。如果某人不是管理员,要获得 true,您可以执行 person.isNotAdmin = !!admin.id。用例很少,但有的时候很简洁。

解决方案5:

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

!! 将其右侧的值转换为其等效的布尔值。 (想想穷人的“类型转换”方式)。它的意图通常是为了向读者传达代码并不关心变量中的值是什么,而是它的"truth" value是什么。

或者在右边的布尔值的情况下,它什么也不做。

@Daniel:! 仍然将值翻转到右侧。在布尔值的情况下,最右边的 ! 否定该值,而最左边的 ! 再次否定它。净效果是没有变化,但大多数引擎会为双重否定生成操作码。

但重点是什么?如果我这样做 if(0){... Javascript 已经知道这是错误的。为什么说if(!!0){...更好?

关键是您可能不知道其内容的变量;如果它可以是整数或字符串、对象或 null、未定义等。这是测试存在性的简单方法。

解决方案6:

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

!!foo 应用一元非运算符两次,用于转换为布尔类型,类似于使用一元加 +foo 转换为数字并连接空字符串 ‘’+foo 以转换为字符串。

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

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

但是你可能会遇到 instanceof 的问题。 new Boolean(1) instanceof Object -> true !!1 instanceof Object -> false

不,您不能:请注意,在没有 new 的情况下调用构造函数-正如我的回答中明确提到的

极好的!当您需要将带有“0”的字符串评估为假而不是真时,这对于一些小技巧很有用。 (即从选择中读取值时,因为它们被读取为字符串)。因此,如果您想将“0”视为负数(布尔型 false),假设 x="0" 只需执行:x=!!+x; //false 与 Boolean(Number(x)) 相同 Number(或 +x)将字符串“0”转换为 0,它的评估结果为假,然后布尔 (!!x) 直接将其转换为布尔值。十分简单!

@DiegoDD 你为什么选择 !!+x 和 x !== "0"?

@placeybordeaux 因为例如您可能希望转换该值并将其分配给其他变量,无论您是否要将其与其他变量进行比较。

解决方案7:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

这么多答案做了一半的工作。是的,!!X 可以理解为“X [表示为布尔值] 的真实性”。但实际上,!! 对于确定单个变量是(或者即使许多变量是)真还是假并不是那么重要。 !!myVar === true 与 myVar 相同。将 !!X 与“真正的”布尔值进行比较并不是很有用。

您使用 !! 获得的唯一好处是能够以可重复、标准化(且 JSLint 友好)的方式检查多个变量的真实性相互。

简单地铸造:(

那是…

0 === 假是假的。

!!0 === 假是真的。

上面的用处不大。 if (!0) 为您提供与 if (!!0 === false) 相同的结果。我想不出将变量转换为布尔值然后与“真实”布尔值进行比较的好案例。

请参阅 JSLint’s directions 中的“== 和 !=”(注意:Crockford 正在稍微移动他的网站;该链接可能会在某个时候失效)以了解原因:

== 和 != 运算符在比较之前进行强制类型转换。这很糟糕,因为它会导致 ’ \t\r\n’ == 0 为真。这可以掩盖类型错误。 JSLint 无法可靠地确定 == 是否被正确使用,因此最好不要使用 == 和 != 并始终使用更可靠的 === 和 !== 运算符。如果你只关心一个值是真还是假,那么使用简写形式。而不是 (foo != 0) 只是说 (foo) 而不是 (foo == 0) 说 (!foo)

请注意,在将布尔值与数字进行比较时,有些 unintuitive cases 会将布尔值转换为数字(true 转换为 1,false 转换为 0)。在这种情况下,!! 可能对心理有用。但是,在这些情况下,您将非布尔值与硬类型布尔值进行比较,这在 imo 中是一个严重的错误。if (-1) 仍然是此处的方法。

╔═══════════════════════════════════════╦═══════════════════╦═══════════╗
║               OriginalEquivalentResult   ║
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
║ 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());

由于 some historical Windows jive,这将在消息框中输出 -1!在 cmd.exe 提示符下试试看!但是 WScript.echo(-1 == test()) 仍然给你 0,或者 WScript 的 false。 Look away. It’s hideous.

比较真实性:)

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

假设我们有 myVar1 = 0; 和 myVar2 = undefined;。

myVar1 === myVar2 为 0 === 未定义,显然是错误的。

!!myVar1 === !!myVar2 是 !!0 === !!undefined 并且是真的!一样的真实! (在这种情况下,两者都“具有虚假的真实性”。)

因此,您真正需要使用“布尔转换变量”的唯一地方是,您需要检查两个变量是否具有 same 真实性,对吗?也就是说,如果您需要查看两个变量是否都为真或都为假(或不是),则使用!!,即相等(或不)真实性。

我想不出一个伟大的、非人为的用例来做这个副手。也许您在表单中有“链接”字段?

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 日:

需要显式布尔值的 3rd 方库

这是一个有趣的案例…当第 3 方库需要明确的布尔值时,!! 可能很有用。

反应

例如,False in JSX (React) has a special meaning 不会因简单的虚假而触发。如果您尝试在 JSX 中返回类似以下内容,则期望 messageCount 中为 int …

{messageCount &&

You have messages!
}

…当您的消息为零时,您可能会惊讶地看到 React 呈现 0。您必须显式返回 false 才能使 JSX 不呈现。上面的语句返回 0,JSX 会按照它应该的方式愉快地渲染它。它不能告诉您没有 Count: {messageCount}。

一种修复方法是使用 bangbang,它将 0 强制转换为 !!0,这是错误的:{!!messageCount && You have messages!}

JSX 的文档建议您更加明确,编写自注释代码,并使用比较来强制为布尔值。 {messageCount > 0 && 你有消息!}

我更愿意自己用三元处理虚假 - {messageCount ? 你有消息! : false}

打字稿

Typescript 中的相同处理:如果您有一个返回布尔值的函数(或者您正在为布尔变量分配一个值),那么您 [通常] 不能返回/分配一个 boolean-y 值;它必须是强类型的布尔值。这意味着,如果 myObject 是强类型,return !myObject; 适用于返回布尔值的函数,但 return myObject; 不适用。您必须 return !!myObject (或以另一种方式转换为正确的布尔值)才能匹配 Typescript 的期望。

Typescript 的例外?如果 myObject 是 any,那么您就回到了 JavaScript 的狂野西部并且可以在没有 !! 的情况下返回它,即使您的返回类型是布尔值。

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

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

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

很好的解释。所以你会说!!在这个 Worker feature detection 示例中不是绝对必要的吗? if (!!window.Worker)

不,你不需要它。真实性和 true “外部”在 if 中的操作完全相同。我一直在尝试,但我想不出有什么理由更喜欢将真实性转换为布尔值,而不是上面那种令人费解的“比较真实性”案例,除非您稍后重用该值时的可读性,如 {3 } 库示例。但即便如此,这也是一条信息丢失的捷径,我认为你最好每次都评估真实性。

解决方案8:

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

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

true === !!10

false === !!0

解决方案9:

huntsbot.com – 高效赚钱,自由工作

它将后缀转换为布尔值。

解决方案10:

与HuntsBot一起,探索全球自由职业机会–huntsbot.com

这是一个双 not 操作。第一个 ! 将值转换为布尔值并反转其逻辑值。第二个 ! 反转逻辑值。

解决方案11:

huntsbot.com – 高效赚钱,自由工作

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

var foo = "Hello World!";

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

原文链接:https://www.huntsbot.com/qa/bL71/what-is-the-not-not-operator-in-javascript?lang=zh_CN

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值