【问题标题】:Understanding type coercion in JavaScript了解 JavaScript 中的类型强制
【发布时间】:2019-07-10 03:14:53
【问题描述】:

我知道== 运算符执行类型强制。但我无法理解以下行为。

const x = new Boolean(false);

if (x) {
  console.log("if(x) is true");
}

if (x == false) {
  console.log("if(x == false) is true");
}

令人惊讶的是,上面的 sn-p 打印了两行:

if(x) is true if(x == false) is true

有人可以解释这种奇怪的行为还是我缺少一些基本的东西?

【问题讨论】:

  • @JohnMontgomery 那么为什么语句评估为真
  • 这不是类型强制的事情,这是拳击的事情。这正是你不做new Boolean()new Number()new String()的原因。
  • 请参考以下文档来自精通Kyle Simpson的关于Falsy Objects的文档。我实际上建议您免费阅读整本书。

标签: javascript node.js type-coercion


【解决方案1】:

正如其他答案所提到的,那是因为 x 是一个对象 - 一个布尔对象,但仍然是一个对象,因为您使用的是 new 运算符 - 并且仅在您将 x 与 @ 进行比较时才会强制执行987654326@:if (x) 正在检查 x 是否为 truthy 值,因此不需要强制(不涉及其他操作数):对象始终为“真”(weeeell ......几乎总是:@ 987654329@ 返回 object 但这是一个虚假值。但那是另一回事了……)。

点击toPrimitive 符号,您可以轻松检查何时调用强制:

var x = new Boolean(false);

// first of all, if it wasn't an object you couldn't
// do this
x[Symbol.toPrimitive] = function(hint) {
  console.log({hint});
  return this.valueOf();
}

// no console.log yet
if (x) {
  console.log("if(x) is true");
}

// here you got the console.log before the one
// inside the block, since the coercion happens
// in the `if`
if (x == false) {
  console.log("if(x == false) is true");
}

【讨论】:

  • 我还在努力理解它。如果 x 是真值强制应该将其转换为真,因此,x == false 在第二个 if 语句中应该是假的,但事实并非如此
  • 我认为您缺少强制的基础:当您比较 两个 事物时会发生这种情况:您需要 两个 操作数我>。 if (x) 不会将 x 与任何东西进行比较:它只是检查 x 是否为真值——注意! "truthy" 不是 "equals to true",并且 "truthy" 本身不是 type,因此没有强制。当您执行 x == false 时,您正在比较 两个 事物,并且由于您使用的是抽象相等 (==),因此执行了强制。
【解决方案2】:

new Boolean(false) 产生一个对象。对象总是truthy,即使它们包装了一个虚假的原始值。例如,new String("") 也是真的,尽管 "" 是假的。

另一方面,当您执行new Boolean(false) == false 时,它会将对象强制为其原始值以进行比较。顺便说一句,new Boolean(false) === false 不是 true,因为它们的类型不匹配。

作为一般规则,除非您有特定原因,否则不应将对象构造函数用于原始类型,以避免此类意外行为。

【讨论】:

    【解决方案3】:

    当您在 javascript 中执行 if (expression) 时,表达式会被强制转换为布尔值。

    有点令人困惑的是,Boolean(new Boolean(false)) 的计算结果为 true,因为正如尼克所说,它仍然是一个对象。这就是导致您感到困惑的行为的原因。

    阅读更多信息https://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/

    【讨论】:

      【解决方案4】:

      如果你写

      const x = new Boolean(false);
      

      typeof x 将返回 objectobject 的类型是“truthy”,这意味着如果没有像 == 这样的运算符,它的计算结果为 true。但是,它的值是false,这就是为什么第二个语句的计算结果也为真。

      所以if 语句的行为不同,因为不带运算符的if 检查类型是真还是假(在这种情况下为真 -> 真)以及带有比较 (==) 的 if 调用 .valueOf()这是false

      无论如何,您都不应该在这种情况下使用 new 包装器。

      const x = false;
      

      就够了。对于强制转换,您可以使用 Boolean() 而不使用 new 包装器。

      要检查一个值是否为真,可以使用双重否定:

      const x = new Boolean(false);
      
      if (x) console.log(!!x);
      
      if (x == false) console.log(x.valueOf());

      【讨论】:

        【解决方案5】:

        您应该使用Boolean(false) 而不是new Boolean(false),因为Boolean 是一个函数。

        否则会得到一个空对象{},它与函数本身返回的类型不同,即boolean

        const x = new Boolean(false);
        const y = Boolean(false);
        
        console.log(x, typeof x);
        console.log(y, typeof y);

        在你的第一个测试中,你只检查值是否为真,空对象为真,因为x = {},测试通过:

        const x = new Boolean(false);
        
        console.log(x, !!x, !!{}, Boolean(x))
        
        if (x) {
          console.log("if(x) is true");
        }

        但是,当使用== 时,运算符使用x.valueOfnew Boolean(false) 强制转换为其原始值,即false,因此等式通过了。

        const x = new Boolean(false);
        
        console.log(x.valueOf())

        【讨论】:

          猜你喜欢
          • 2014-12-31
          • 1970-01-01
          • 1970-01-01
          • 2021-04-15
          • 1970-01-01
          • 2020-11-14
          • 2011-12-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多