本文将介绍一段使用JavaScript
隐式类型转换输出"nb"
的代码,并讲解具体的转换过程。
预备知识
请先阅读文章ECMAScript7规范中的ToPrimitive抽象操作。
代码
([][[]]+[])[+!![]]+([]+{})[!+[]+!![]] // "nb"
转换过程
我们分四部分讲解具体的转换过程:
- ([][[]]+[])
- [+!![]]
- ([]+{})
- [!+[]+!![]]
([][[]]+[])
-
[]
,一个空数组; -
[[]]
,紧跟在数组后面的[
的语义应该是表示属性操作,类似于obj[key]
中[]
的作用,而不是表示数组。这个里面,既然外层的[]
表示获取属性的运算符,里面的[]
肯定就表示key
了。因为key
是原始数据类型,所以会调用ToPrimitive
抽象操作把[]
转化为原始数据类型,也就是空字符串""
,所以上面两个结合起来就是:var a = [] var b = [] a[b] // => a[""] => undefined
-
+
,相加操作; -
[]
,空对象,和上面的步骤结合起来就是:undefined + []
相加操作会把操作符两边的操作数通过
ToPrimitive
抽象操作转化为原始数据类型,也就是[]
会变为""
:undefined + ""
相加操作的抽象步骤中,如果有一个操作数是字符串,会调用
ToString
抽象操作把两个操作数都转化为字符串类型,也就是:undefined + "" // => "undefined" + "" => "undefined"
综上,([][[]]+[])
的结果就是字符串"undefined"
。
[+!![]]
-
!![]
,表示把一个数据转化为布尔类型,因为[]
是一个真值,所以!![]
的结果是true
; -
+!![]
,表示把前面的结果转化为数字类型,也就是+true
,true
转化为数字是1
,所以+!![]
的结果是1
; -
[+!![]]
,也就是[1]
,结合第一部分([][[]]+[])
的结果:([][[]]+[])[+!![]] // => "undefined"[1] => 也就是获取字符串"undefined"的第二个字符,也就是"n" => "n"
([]+{})
相加操作会调用ToPrimitive
抽象操作把操作符两边的数据转化为原始数据类型,也就是:
([]+{}) // => "" + "[object Object]" // => "[object Object]"
[!+[]+!![]]
-
+[]
,把数组转化为数字:+[] // => +"" => 0
-
!+[]
,也就是!0
:true
; -
!![]
,true
; -
!+[]+!![]
,也就是true + true
,又是相加操作,因为操作符两边都是布尔类型,所以会转化为数字类型,也就是1 + 1
,也就是2
;
第三部分和第四部分的结果结合起来就是:
([]+{})[!+[]+!![]] // => "[object Object]"[2] => 也就是取字符串"[object Object]"的第三个字符,也就是"b" => "b"
第一二部分和第三四部分结合起来的结果就是:
([][[]]+[])[+!![]]+([]+{})[!+[]+!![]] // => "n" + "b" => "nb"
总结
希望大家看的开心!如果本文有什么错误或者不严谨的地方,欢迎在评论区留言。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。