为什么++ [[]] [+ []] + [+ []]返回字符串“ 10”?

这是有效的,并返回"10"JavaScript中的字符串此处有更多示例):

console.log(++[[]][+[]]+[+[]])

为什么?这是怎么回事

樱小小Tom2020/03/09 20:19:11

逐步操作,+将value转换为数字,如果您将其添加到一个空数组中+[],因为它为空且等于0,它将

所以从那里开始,现在查看您的代码,它是++[[]][+[]]+[+[]]...

他们之间有加号++[[]][+[]]+[+[]]

所以这些[+[]]将返回,[0]因为它们有一个空数组,该数组将被转换为0另一个数组内部...

就像想象的那样,第一个值是一个二维数组,其中包含一个数组...因此[[]][+[]]等于[[]][0]返回的值[]...

最后++将其转换并增加到1...

因此,您可以想象,1+ "0""10"...

为什么返回字符串“ 10”?

十三理查德2020/03/09 20:19:11

可能的最短方法是将表达式评估为没有数字的“ 10”:

+!+[] + [+[]] //“ 10”

-~[] + [+[]] //“ 10”

// ==========说明========= \\

+!+[]+[]转换为0。!0转换为true+true转换为1 -~[]= = -(-1)1

[+[]]+[]转换为0。[0]是具有单个元素0的数组。

然后JS计算1 + [0],即Number + Array表达式。然后ECMA规范起作用:+运算符通过toString()/valueOf()从基本Object原型中调用函数将两个操作数转换为字符串如果一个表达式的两个操作数都只有数字,则它可以作为加法函数。诀窍在于,数组可以轻松地将其元素转换为连接的字符串表示形式。

一些例子:

1 + {} //    "1[object Object]"
1 + [] //    "1"
1 + new Date() //    "1Wed Jun 19 2013 12:13:25 GMT+0400 (Caucasus Standard Time)"

有一个很好的例外,有两个Objects加法导致NaN

[] + []   //    ""
[1] + [2] //    "12"
{} + {}   //    NaN
{a:1} + {b:2}     //    NaN
[1, {}] + [2, {}] //    "1,[object Object]2,[object Object]"
米亚伽罗L2020/03/09 20:19:11
  1. 一元加给定的字符串转换为数字
  2. 给定字符串的增量运算符将转换并递增1
  3. [] ==”。空字符串
  4. +''或+ []的值为0。

    ++[[]][+[]]+[+[]] = 10 
    ++[''][0] + [0] : First part is gives zeroth element of the array which is empty string 
    1+0 
    10
    
乐A2020/03/09 20:19:11

+ []的计算结果为0 [...],然后将其与任何内容求和(+操作),将数组内容转换为其字符串表示形式,该字符串表示形式包含用逗号连接的元素。

像获取数组索引(具有比+操作更高的优先级)之类的其他东西都是有序的,没什么有趣的。

乐小小2020/03/09 20:19:11
++[[]][+[]] => 1 // [+[]] = [0], ++0 = 1
[+[]] => [0]

然后我们有一个字符串连接

1+[0].toString() = 10
→笑里藏刀↓2020/03/09 20:19:11

该评估结果相同但略小

+!![]+''+(+[])
  • []-是转换后的数组,当您对其进行添加或减去时会转换为0,因此+ [] = 0
  • ![]-评估为false,因此!! []评估为true
  • + !! []-将true转换为计算为true的数值,因此在这种情况下为1
  • +''-将空字符串附加到表达式中,导致数字转换为字符串
  • + []-计算为0

所以估计

+(true) + '' + (0)
1 + '' + 0
"10"

所以现在您明白了,尝试以下方法:

_=$=+[],++_+''+$
神无老丝Davaid2020/03/09 20:19:11

以下内容是根据一个博客帖子改编的,该博客帖子回答了我在此问题仍处于关闭状态时发布的该问题。链接指向ECMAScript 3规范(的HTML副本),仍然是当今常用的Web浏览器中JavaScript的基线。

首先,发表评论:这种表达永远不会出现在任何(理智的)生产环境中,并且只能用作练习,以了解读者如何了解JavaScript的肮脏边缘。JavaScript运算符在类型之间进行隐式转换的一般原理以及一些常见的转换都是有用的,但本例中的许多细节都没有。

该表达式++[[]][+[]]+[+[]]最初看起来可能比较强悍和晦涩,但实际上相对容易分解为单独的表达式。为了清楚起见,我在下面仅添加了括号。我可以向您保证,他们什么都不会改变,但是如果您想验证这一点,请随时阅读有关分组运算符的信息因此,该表达式可以更清楚地写为

( ++[[]][+[]] ) + ( [+[]] )

打破这一下来,我们可以通过观察来简化+[]计算结果为0为了使自己满意,请检查一元+运算符,并遵循略带曲折的轨迹,该轨迹最终以ToPrimitive将空数组转换为空字符串,然后最终0ToNumber转换为空字符串现在0我们可以代替的每个实例+[]

( ++[[]][0] ) + [0]

已经更简单了。至于++[[]][0],这是前缀增量运算符++),定义单个元素的数组数组文字的组合,该元素本身就是一个空数组([[]])和在该数组文字所定义的数组上调用属性访问器[0])。

So, we can simplify [[]][0] to just [] and we have ++[], right? In fact, this is not the case because evaluating ++[] throws an error, which may initially seem confusing. However, a little thought about the nature of ++ makes this clear: it’s used to increment a variable (e.g. ++i) or an object property (e.g. ++obj.count). Not only does it evaluate to a value, it also stores that value somewhere. In the case of ++[], it has nowhere to put the new value (whatever it may be) because there is no reference to an object property or variable to update. In spec terms, this is covered by the internal PutValue operation, which is called by the prefix increment operator.

So then, what does ++[[]][0] do? Well, by similar logic as +[], the inner array is converted to 0 and this value is incremented by 1 to give us a final value of 1. The value of property 0 in the outer array is updated to 1 and the whole expression evaluates to 1.

This leaves us with

1 + [0]

... which is a simple use of the addition operator. Both operands are first converted to primitives and if either primitive value is a string, string concatenation is performed, otherwise numeric addition is performed. [0] converts to "0", so string concatenation is used, producing "10".

最后,可能不会立即显而易见的是,覆盖的toString()valueOf()方法之一Array.prototype将更改表达式的结果,因为在将对象转换为原始值时会同时检查和使用两者(如果存在)。例如,以下

Array.prototype.toString = function() {
  return "foo";
};
++[[]][+[]]+[+[]]

...产生"NaNfoo"为什么发生这种情况留给读者作为练习...

番长GO2020/03/09 20:19:11

让我们简单点:

++[[]][+[]]+[+[]] = "10"

var a = [[]][+[]];
var b = [+[]];

// so a == [] and b == [0]

++a;

// then a == 1 and b is still that array [0]
// when you sum the var a and an array, it will sum b as a string just like that:

1 + "0" = "10"