为什么 ++[[]][+[]]+[+[]] 返回字符串“10"? [英] Why does ++[[]][+[]]+[+[]] return the string "10"?

查看:26
本文介绍了为什么 ++[[]][+[]]+[+[]] 返回字符串“10"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是有效的,并在 JavaScript 中返回字符串 "10" (更多例子在这里):

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

为什么?这里发生了什么?

解决方案

如果我们把它分开,就等于:

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

在 JavaScript 中,+[] === 0 确实如此.+ 将某些内容转换为数字,在这种情况下,它将归结为 +""0(请参阅下面的规范详细信息).

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

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

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

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

++ 在它的操作数之前表示加一并返回增加的结果".所以++[[]][0]等价于Number(A) + 1(或+A + 1).>

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

(+[] + 1)+[0]

+[]可以将数组强制为数字0之前,需要先将其强制为字符串,即"" 再说一遍.最后,添加1,结果为1.

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

让我们进一步简化它:

1+[0]

此外,这在 JavaScript 中也是正确的:[0] == "0",因为它连接了一个具有一个元素的数组.Join 将连接由 , 分隔的元素.对于一个元素,您可以推断出此逻辑将生成第一个元素本身.

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

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

<小时>

+[] 的详细说明:

这是一个相当大的迷宫,但是要做到+[],首先它被转换成一个字符串,因为这就是+所说的:

<块引用>

11.4.6 一元 + 运算符

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

产生式 UnaryExpression : + UnaryExpression 的计算如下:

  1. 令 expr 成为计算 UnaryExpression 的结果.

  2. Return ToNumber(GetValue(expr)).

ToNumber() 说:

<块引用>

对象

应用以下步骤:

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

  2. 返回到字符串(primValue).

ToPrimitive() 说:

<块引用>

对象

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

[[DefaultValue]] 说:

<块引用>

8.12.8 [[DefaultValue]](提示)

当使用hint String调用O的[[DefaultValue]]内部方法时,采取如下步骤:

  1. 令 toString 为调用对象 O 的 [[Get]] 内部方法的结果,参数为toString".

  2. 如果 IsCallable(toString) 为真,则

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

B.如果 str 是原始值,则返回 str.

数组的 .toString 表示:

<块引用>

15.4.4.2 Array.prototype.toString()

调用toString方法时,采取如下步骤:

  1. 令数组成为对 this 值调用 ToObject 的结果.

  2. 令 func 是调用数组的 [[Get]] 内部方法的结果,参数为join".

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

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

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

同样,+ 定义为:

<块引用>

11.4.6 一元 + 运算符

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

产生式 UnaryExpression : + UnaryExpression 的计算如下:

  1. 令 expr 成为计算 UnaryExpression 的结果.

  2. Return ToNumber(GetValue(expr)).

ToNumber"" 定义为:

<块引用>

StringNumericLiteral ::: [empty] 的 MV 为 0.

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

This is valid and returns the string "10" in JavaScript (more examples here):

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

Why? What is happening here?

解决方案

If we split it up, the mess is equal to:

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

In JavaScript, it is true that +[] === 0. + converts something into a number, and in this case it will come down to +"" or 0 (see specification details below).

Therefore, we can simplify it (++ has precendence over +):

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

Because [[]][0] means: get the first element from [[]], it is true that:

[[]][0] returns the inner array ([]). Due to references it's wrong to say [[]][0] === [], but let's call the inner array A to avoid the wrong notation.

++ before its operand means "increment by one and return the incremented result". So ++[[]][0] is equivalent to Number(A) + 1 (or +A + 1).

Again, we can simplify the mess into something more legible. Let's substitute [] back for A:

(+[] + 1)
+
[0]

Before +[] can coerce the array into the number 0, it needs to be coerced into a string first, which is "", again. Finally, 1 is added, which results in 1.

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

Let's simplify it even more:

1
+
[0]

Also, this is true in JavaScript: [0] == "0", because it's joining an array with one element. Joining will concatenate the elements separated by ,. With one element, you can deduce that this logic will result in the first element itself.

In this case, + sees two operands: a number and an array. It’s now trying to coerce the two into the same type. First, the array is coerced into the string "0", next, the number is coerced into a string ("1"). Number + String === String.

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


Specification details for +[]:

This is quite a maze, but to do +[], first it is being converted to a string because that's what + says:

11.4.6 Unary + Operator

The unary + operator converts its operand to Number type.

The production UnaryExpression : + UnaryExpression is evaluated as follows:

  1. Let expr be the result of evaluating UnaryExpression.

  2. Return ToNumber(GetValue(expr)).

ToNumber() says:

Object

Apply the following steps:

  1. Let primValue be ToPrimitive(input argument, hint String).

  2. Return ToString(primValue).

ToPrimitive() says:

Object

Return a default value for the Object. The default value of an object is retrieved by calling the [[DefaultValue]] internal method of the object, passing the optional hint PreferredType. The behaviour of the [[DefaultValue]] internal method is defined by this specification for all native ECMAScript objects in 8.12.8.

[[DefaultValue]] says:

8.12.8 [[DefaultValue]] (hint)

When the [[DefaultValue]] internal method of O is called with hint String, the following steps are taken:

  1. Let toString be the result of calling the [[Get]] internal method of object O with argument "toString".

  2. If IsCallable(toString) is true then,

a. Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and an empty argument list.

b. If str is a primitive value, return str.

The .toString of an array says:

15.4.4.2 Array.prototype.toString ( )

When the toString method is called, the following steps are taken:

  1. Let array be the result of calling ToObject on the this value.

  2. Let func be the result of calling the [[Get]] internal method of array with argument "join".

  3. If IsCallable(func) is false, then let func be the standard built-in method Object.prototype.toString (15.2.4.2).

  4. Return the result of calling the [[Call]] internal method of func providing array as the this value and an empty arguments list.

So +[] comes down to +"", because [].join() === "".

Again, the + is defined as:

11.4.6 Unary + Operator

The unary + operator converts its operand to Number type.

The production UnaryExpression : + UnaryExpression is evaluated as follows:

  1. Let expr be the result of evaluating UnaryExpression.

  2. Return ToNumber(GetValue(expr)).

ToNumber is defined for "" as:

The MV of StringNumericLiteral ::: [empty] is 0.

So +"" === 0, and thus +[] === 0.

这篇关于为什么 ++[[]][+[]]+[+[]] 返回字符串“10"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆