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

2020/09/15 20:31 · javascript ·  · 0评论

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

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

为什么?这是怎么回事

如果我们将其拆分,则混乱等于:

++[[]][+[]]
+
[+[]]

在JavaScript中,确实是这样+[] === 0+将某物转换为数字,在这种情况下,它将归结为+""0(请参见下面的规范详细信息)。

因此,我们可以简化它(++优先于+):

++[[]][0]
+
[0]

因为[[]][0]意思是:从中获取第一个元素[[]],所以确实:

[[]][0]返回内部数组([])。由于引用,说错了[[]][0] === [],但是让我们调用内部数组A以避免错误的表示法。

++在其操作数之前表示“加1并返回加结果”。因此++[[]][0]等于Number(A) + 1(或+A + 1)。

同样,我们可以将混乱简化为更清晰的内容。让我们替换[]A

(+[] + 1)
+
[0]

+[]将数组强制转换为number之前0,需要先将其强制转换为字符串,即""再次。最后1添加,结果为1

  • (+[] + 1) === (+"" + 1)
  • (+"" + 1) === (0 + 1)
  • (0 + 1) === 1

让我们进一步简化它:

1
+
[0]

同样,在JavaScript:中也是如此[0] == "0",因为它是将一个元素与一个数组连接在一起。连接将连接由分隔的元素,使用一个元素,您可以推断出此逻辑将导致第一个元素本身。

在这种情况下,+将看到两个操作数:一个数字和一个数组。现在,它试图将两者强制转换为同一类型。首先,将数组强制转换为字符串"0",然后将数字强制转换为字符串("1")。Number +字符串===String

"1" + "0" === "10" // Yay!

规格详细信息+[]

+[]真是一个迷宫,但要做到一点,首先要将其转换为字符串,因为这是这样+说的:

11.4.6一元+运算符

一元+运算符将其操作数转换为Number类型。

生产UnaryExpression:+ UnaryExpression的评估如下:

  1. 令expr为评估UnaryExpression的结果。

  2. 返回ToNumber(GetValue(expr))。

ToNumber() 说:

目的

应用以下步骤:

  1. 令primValue为ToPrimitive(输入参数,提示字符串)。

  2. 返回ToString(primValue)。

ToPrimitive() 说:

目的

返回对象的默认值。通过调用对象的[[DefaultValue]]内部方法并传递可选提示PreferredType来检索对象的默认值。本规范为8.12.8中的所有本机ECMAScript对象定义了[[DefaultValue]]内部方法的行为。

[[DefaultValue]] 说:

8.12.8 [[DefaultValue]](提示)

使用提示字符串调用O的[[DefaultValue]]内部方法时,将执行以下步骤:

  1. 令toString为使用参数“ toString”调用对象O的[[Get]]内部方法的结果。

  2. 如果IsCallable(toString)为true,

一个。令str为调用toString的[[Call]]内部方法的结果,其中O为this值,并且参数列表为空。

b。如果str是原始值,则返回str。

.toString数组的说:

15.4.4.2 Array.prototype.toString()

调用toString方法时,将执行以下步骤:

  1. 令array为在this值上调用ToObject的结果。

  2. 令func为使用参数“ join”调用array的[[Get]]内部方法的结果。

  3. 如果IsCallable(func)为false,则将func设为标准的内置方法Object.prototype.toString(15.2.4.2)。

  4. 返回调用func提供数组的[[Call]]内部方法的结果作为this值和空参数列表。

所以+[]归结为+"",因为[].join() === ""

同样,+定义为:

11.4.6一元+运算符

一元+运算符将其操作数转换为Number类型。

生产UnaryExpression:+ UnaryExpression的评估如下:

  1. 令expr为评估UnaryExpression的结果。

  2. 返回ToNumber(GetValue(expr))。

ToNumber被定义为""

StringNumericLiteral ::: [空]的MV为0。

所以+"" === 0,因此+[] === 0

++[[]][+[]] => 1 // [+[]] = [0], ++0 = 1
[+[]] => [0]

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

1+[0].toString() = 10

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

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

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

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

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

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

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

因此,我们可以简化[[]][0]为公正[],我们有++[],对吧?实际上,情况并非如此,因为评估++[]会引发错误,这在开始时可能会引起混淆。但是,对的性质稍加思考就++可以清楚地看出这一点:它用于递增变量(例如++i)或对象属性(例如++obj.count)。它不仅会评估一个值,还会将该值存储在某个位置。在的情况下++[],它无处可放新值(无论它可能在哪里),因为没有对要更新的对象属性或变量的引用。用规范术语来说,这由内部PutValue操作覆盖,该操作由前缀增量运算符调用。

那么,那该怎么++[[]][0]办呢?嗯,通过类似的逻辑+[],内部数组被转换为,0并且该值增加,1从而得出最终值10外部数组中的property值更新为1,整个表达式的求值为1

这给我们留下了

1 + [0]

...这是加法运算符的简单用法首先两个操作数都转换为基元,并且如果任一基元值是字符串,则执行字符串连接,否则执行数字加法。[0]转换为"0",因此使用字符串连接,产生"10"

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

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

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

让我们简单点:

++[[]][+[]]+[+[]] = "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"

该评估结果相同但略小

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

所以估计

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

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

_=$=+[],++_+''+$

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

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

将表达式评估为没有数字的“ 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]"

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

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

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

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

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

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

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

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

  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
本文地址:http://javascript.askforanswer.com/weishenme-fanhuizifuchuan-10.html
文章标签: ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!