简体   繁体   English

为什么(!+ [] + [])是'true'而且(false + [])在Javascript中是'false'?

[英]Why (!+[]+[]) is 'true' and (false + []) is 'false' in Javascript?

I'm looking at ECMA-262 grammar for a definition of the next code bellow: 我正在查看ECMA-262语法,以获得下一个代码的定义:

 const v = (! + [] + []); const c = (false + []); console.log(v); console.log(c); 

What is BEHIND it? 什么是它?

Until now I did not find anything helpful, does anyone know why it gives those results or have references about it? 到目前为止,我没有找到任何有用的信息,是否有人知道为什么它会给出这些结果或有关于它的参考?

This is because when you try to apply an operator to different data structure JavaScript engine applies coercion . 这是因为当您尝试将运算符应用于不同的数据结构时,JavaScript引擎会应用强制

In the first case what it does is : 在第一种情况下,它的作用是:

  1. Convert first [] to primitive, which is performed by invoking toString() method of array. 将first []转换为primitive,这是通过调用array的toString()方法执行的。 The toString method joins all the array values to a string. toString方法将所有数组值连接到一个字符串。 If you wold have something like (false + [1,2,3]) you would get : false1,2,3 如果你有类似的东西(false + [1,2,3])你会得到: false1,2,3

  2. The second step is to bring the boolean in the String context 第二步是将布尔值放在String上下文中

  3. Now that we have all the values in the same datastructure, it will simply concatenate all of them 现在我们拥有相同数据结构中的所有值,它将简单地连接所有这些值

In your case (! + [] + []) is evaluated to 'true' which has the length of 4. 在你的情况下(! + [] + [])被评估为'true',其长度为4。

The book You Don't Know JS: Types & Grammar is a gem for understanding all these kind of weird operations JavaScript engine does. 你不了解JS:Types&Grammar这本书是理解JavaScript引擎所做的所有这些奇怪操作的宝石。

EDIT : As Felix Kling was suggesting ! 编辑 :正如Felix Kling所暗示的那样! operator has a different role in the evaluation of (! + [] + []) . 运算符在(! + [] + [])的求值中具有不同的作用。

In this case what happens is that : 在这种情况下会发生的是:

  • ! + [] ! + [] is evaluated to true. ! + []被评估为true。 This is because ! + [] 这是因为! + [] ! + [] puts them in a Boolean context where [toNumber] operation is applied on [] which is 0 and !0 is true ! + []将它们放在一个布尔上下文中,其中[toNumber]操作应用于[],它为0!0true

  • true + [] is evaluated to 'true' . true + []被评估为'true' This is because when you try to add a boolean with an object (array is derived from object) [toString] operation is applied to both items. 这是因为当您尝试使用对象添加布尔值(数组是从对象派生的)时, [toString]操作将应用于这两个项目。

Actually, for understand why you are getting that result, you have to think how the expression is evaluated (ie, in what order?). 实际上,为了理解你为什么得到这个结果,你必须考虑如何评估表达式(即,以什么顺序?)。 If we observe your first expression: 如果我们观察你的第一个表达:

const v = (! + [] + []);

we can see that there exists one logical operator (the logical NOT ! ), one unary operator ( + ) and one arithmetic operator, actually the addition + . 我们可以看到存在一个逻辑运算符(逻辑NOT ! ),一个一元运算符( + )和一个算术运算符,实际上是加+ If we take into account the order of evaluation of that expression, we can write it like this: 如果我们考虑到该表达式的评估顺序,我们可以这样写:

const v = ( (!(+[])) + [] );

Now, the first expression evaluated here is +[] , and from the documentation of the unary plus operator you get: 现在,这里评估的第一个表达式是+[] ,并且从unary plus运算符的文档中得到:

The unary plus operator precedes its operand and evaluates to its operand but attempts to convert it into a number, if it isn't already... 一元加运算符在其操作数之前,并计算其操作数,但尝试将其转换为数字,如果它还没有...

Actually, the previous evaluation results in 0 (a coercion occurs in where the empty array is casted to number type) as you can check on next example: 实际上,之前的评估结果为0 (强制发生在将空数组转换为数字类型的位置),您可以查看下一个示例:

 console.log(+[]); 

So now, the expression is reduced to 所以现在,表达式减少到了

const v = ( (!0) + [] );

Again, reading some documentation of this logical not operator you can found: 再次,阅读这个逻辑非运算符的一些文档,您可以找到:

Returns false if its single operand can be converted to true; 如果单个操作数可以转换为true,则返回false; otherwise, returns true. 否则,返回true。

So, !0 is reduced to true (another coercion occurs in where the number zero is casted to boolean type) as you can check on next example: 所以, !0被减少为true (另一个强制发生在数字零被转换为布尔类型的位置),你可以检查下一个例子:

 console.log(!0); 

Now, we have next expression where the addition operator comes into play: 现在,我们有下一个表达式,其中添加运算符发挥作用:

const v = ( true + [] );

The addition operator produces the sum of numeric operands or string concatenation. 加法运算符生成数字操作数或字符串连接的总和。

In this case, the operator will do string concatenation since the operands aren't numbers. 在这种情况下,操作符将执行字符串连接,因为操作数不是数字。 So, here is where a new coercion (basically a implicit cast of types) takes places again, because it need to convert both of the operand to strings: 所以,这里是一个新的强制 (基本上是类型的隐式转换)再次发生的地方,因为它需要将操作数转换为字符串:

  • true is converted to string "true" using the method toString() of the Boolean type. 使用布尔类型的toString()方法将true转换为字符串"true"
  • and the empty array [] is converted to the empty string "" using the available toString() method of Array type. 并使用Array类型的可用toString()方法将空数组[]转换为空字符串""

And finally, our expression is reduce to: 最后,我们的表达式减少为:

const v = "true" + ""; // or simply "true".

 const v = (! + [] + []); console.log("value: " + v, "type: " + typeof(v)); 

The second expression should be easy to analyze for your own now, since it is a simplified version of the first one. 第二个表达式现在应该很容易分析,因为它是第一个表达式的简化版本。

 const v = (! + [] + []); const c = (false + []); console.log(v); console.log(c); 

If you take out the .length , you see that the results are: true and false and that these (the results of the + operations) are not arrays but strings, and true is 4 characters long and false is 5. 如果你取出.length ,你会看到结果是: truefalse ,并且这些( +操作的结果)不是数组而是字符串,而true是4个字符长, false是5。

Using your link above, it looks like this is at least partly relevant: 使用上面的链接,看起来这至少部分相关:

12.7.3 The Addition operator ( + ) 12.7.3加法运算符(+)

NOTE The addition operator either performs string concatenation or numeric addition. 注意加法运算符可以执行字符串连接或数字加法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM