了解JavaScript中的平等
#javascript #网络开发人员 #node #howto

我们都去过那里…您使用==比较了两个值,收到一个完全出乎意料的结果,而Wonder wt*正在进行?! - 只有equality ==运算符。

equality ==运算符具有以下语法。

x == y

需要两个操作数,xy,将它们转换为相同的类型,按值进行比较并返回Boolean结果。

始终使用严格的平等===操作员。实际上,使用==而不是===没有任何好处,除非您的目标是将错误引入您的代码库。

但是您没有来这里,所以我可以告诉您开始使用===。只需查看下面的代码即可。您想知道如何解释它,不是吗? - 是的,您应该知道。您正在使用JavaScript,这是一个JavaScript功能 - 因此,拥抱它

'' == '0'             // Result: false
0 == ''               // Result: true
0 == '0'              // Result: true

false == undefined    // Result: false
false == null         // Result: false
null == undefined     // Result: true

[] == 0               // Result: true
[] == '0'             // Result: false
['a', 'b'] == 'a,b'   // Result: true

NaN == NaN            // Result: false
'\n\r\t' == 0         // Result: true

Isloosely equorithm

当您在引擎盖下使用==时,该算法会启动并给出比较的结果。所以,是的,这是我们痛苦的方法。

该算法在ECMAScript specification中进行了描述,基本上每个JavaScript engine都必须按照所述实施。

通常用某种图表或流程图表示算法,但是由于我擅长绘画,所以我向您介绍了这个宏伟的pseudocode

Take two operands, `x` and `y`, as an input

If type of `x` is the same as type of `y`
  If type of `x` is `Undefined`
    return `true`
  If type of `x` is `Null`
    return `true`

  If type of `x` is `Number`
    If `x` is `NaN`
      return `false`
    If `y` is `NaN`
      return `false`
    If `x` is the same as `y`
      return `true`
    If `x` is `-0` and `y` is `+0`
      return `true`
    if `x` is `+0` and `y` is `-0`
      return `true`
    return `false`

  If the type of `x` is `String`
    If `x` and `y` are exactly the same sequence of characters
      return `true`
    return `false`

  If the type of `x` is `Boolean`
    If `x` and `y` are both `true`
      return `true`
    If `x` and `y` are both `false`
      return `true`
    return `false`

  If `x` and `y` refer to the same object
    return `true`

  return `false`

If `x` is `null` and `y` is `undefined`
  return `true`
If `x` is `undefined` and `y` is `null`
  return `true`.

If type of `x` is `Number` and type of `y` is `String`
  Convert `y` to `Number`
  Return the result of the comparison `x == y`
If type of `x` is `String` and type of `y` is `Number`
  Convert `x` to `Number`
  Return the result of the comparison `x == y`

If type of `x` is `Boolean`
  Convert `x` to `Number`
  Return the result of the comparison `x == y`
If type of `y` is `Boolean`
  Convert `y` to `Number`
  Return the result of the comparison `x == y`

If type of `x` is either `String` or `Number` and type of `y` is `Object`
  Convert `y` to primitive value
  Return the result of the comparison `x == y`
If type of `x` is `Object` and type of `y` is either `String` or `Number`
  Convert `x` to primitive value
  Return the result of the comparison `x == y`

Return `false`

请记住,算法的某些部分在伪代表中缺少。如果您想查看详细的规格,请在Ecmascript网站上查看。

是的,我知道,这只是一堆IF语句和转换。这个转换部分确实是重要的。您会看到,当类型相同时,==的行为与===运算符完全相同。重要的区别是,当类型不同时,==会强制强制。

胁迫是一个花式的JavaScript术语,当我们谈论从一个值类型转换为另一种值,例如从字符串到数字。胁迫在==比较中起重要作用。

如果您不想记住整个算法,请以这种方式考虑一下。如果操作数没有相同的类型,则将其转换为Number。当类型相同时,按值比较操作数。

对原始的对象

在我们关注一些示例之前,更重要的是将Object类型值转换为原始值。

在JavaScript中,有7个原始值: string number bigint boolean 未定义的 null 符号

Object类型的值可以通过==运算符自动将其转换为原始值。当一个操作数的类型为Object时,另一个操作数具有原始类型之一。

Object转换为原始价值时,JavaScript将做几件事。它将首先尝试调用内置的原型方法valueOf。如果valueOf不返回原始值,则内置的原型方法toString将被称为接下来。

正如JavaScript中几乎所有的行为一样,这种行为有几个边缘案例,可以修改和覆盖,但是您现在不必担心它。

例子

仍然记得从一开始就记得该代码样本了吗?现在,当我们知道algorithm works

我将在这里做一个假设。 ==左侧的操作数将称为x,右侧的操作数将称为y。从此开始,让我们开始。

请记住,如果操作数没有相同的类型,则==将执行类型转换,只要操作数具有不同的类型。只有这样,才能按值比较操作数。

样本01

'' == '0'
// Result: false

这个非常简单。这两个操作数具有相同类型的String。这意味着将按价值比较奥运会。由于值不相同,因此结果为false

样本02

0 == ''
// Result: true

操作数的类型xNumber,操作数的类型yString。类型不一样,y将转换为Number

空字符串''转换为Number,将为0。通过在浏览器的控制台中运行Number('')来测试它。

转换完成后,将按值比较操作数。由于值相同,因此0确实等于0,结果将为true

样本03

0 == '0'              // Result: true

操作数的类型xNumber,而操作数y的类型为String。操作数y将转换为Number

'0'转换为Number时,其值将为0。通过在浏览器的控制台中运行Number('0')来测试它。

转换完成后,将按值比较操作数。由于值相同,因此0确实等于0,结果将为true

样本04

false == undefined    // Result: false
false == null         // Result: false
null == undefined     // Result: true

我将这些示例分组在一起,因为这种行为的推理几乎是相同的。

根据算法,undefined只能等于undefinednull。对于null,它也只能等于nullundefined。因此,将它们与false进行比较将始终导致false

样本05

[] == 0               // Result: true

操作数xObject的类型,操作数y的类型为String。正如我们已经知道的那样,在可以通过价值比较它们之前,将发生类型转换。在这种情况下,操作数x将转换为原始值。这意味着koude16 to primitive转换将开始。

因此,让我们看看[]转换为原始价值的样子。方法valueOf将直接在[]上调用。通过在浏览器的控制台中运行[].valueOf()来对其进行测试。此操作的结果将是[]

您可以看到,我们仍然有不是原始值的[],因此toString()被调用。通过在浏览器的控制台中运行[].toString()来测试它。返回的值是'',它是原始值。这样,将Object转换为原始价值。

但是,仔细看,操作数仍然具有不同的类型,x现在是'',它是String类型,而y仍然是0,它是Number类型。转换必须继续。

现在,x将转换为Number。从以前的示例中,我们已经知道''将在转换后成为0。转换完成后,将按值比较操作数。由于值相同,因此0确实等于0,结果将为true

样本06

[] == '0'             // Result: false

操作数xObject的类型,但是操作数yString的类型。具有Value []的操作数x将转换为原始值。我们已经知道,从Sample 05中,此转换的结果将是空字符串''。转换后,操作数x将具有值为''和type String

由于两个歌剧院现在都是相同类型的String,因此已完成转换。当按值进行比较时,'''0'不同,因此比较为false

样本07

['a', 'b'] == 'a,b'   // Result: true

操作数xObject的类型,操作数yString的类型。在转换步骤中,Object将转换为to primitive值。

转换后,操作数x将具有值为'a,b'和type String。通过在浏览器的控制台中运行['a', 'b'].toString()来测试它。

两个操作数现在都是String的类型。当按值比较时,结果为true,因为值相同。

样本08

NaN == NaN            // Result: false

这个非常奇怪而又简单。将任何值与NaN进行比较总是会导致false。即使将NaNNaN进行了比较,也很奇怪。

样本09

'\n\r\t' == 0         // Result: true

操作数具有不同的类型,因此需要转换。由于x的类型为String,它将转换为Number。转换后,'\n\r\t'将为0。现在,当通过值比较时,00相同,因此结果是true

如果您想知道'\n\r\t'在转换后如何变成0-这是因为转换为Number的工作方式。

有一些特殊的Single Character Escape Sequences,例如\n(新线路),\t(水平表),\v(垂直标签),\r(马车返回),当将转换为Number时,它们始终将是0。在同一字符串值中包含哪个顺序以及其中有多少个。

都没有关系。

结论

我们都知道JavaScript可能很奇怪,但是如果您在引擎盖下看起来有些清晰,事情就会变得更加清晰。同样的事情是equality ==运算符。从表面上看,这真的很奇怪,但是当您知道其背后的算法时,事情可能会变得容易得多。

无论哪种方式,我都强烈建议始终使用严格的equality ===操作员。但是不要误会我的意思,知道==的工作原理仍然非常重要。毕竟,这是一个始终是语言的JavaScript功能。


查看有关my blog的其他文章。