8

本文将介绍一段使用JavaScript隐式类型转换输出"nb"的代码,并讲解具体的转换过程。

预备知识

请先阅读文章ECMAScript7规范中的ToPrimitive抽象操作

代码

([][[]]+[])[+!![]]+([]+{})[!+[]+!![]] // "nb"

转换过程

我们分四部分讲解具体的转换过程:

  1. ([][[]]+[])
  2. [+!![]]
  3. ([]+{})
  4. [!+[]+!![]]

([][[]]+[])

  1. [],一个空数组;
  2. [[]],紧跟在数组后面的[的语义应该是表示属性操作,类似于obj[key][]的作用,而不是表示数组。这个里面,既然外层的[]表示获取属性的运算符,里面的[]肯定就表示key了。因为key是原始数据类型,所以会调用ToPrimitive抽象操作把[]转化为原始数据类型,也就是空字符串"",所以上面两个结合起来就是:

    var a = []
    var b = []
    a[b] // => a[""] => undefined
  3. +,相加操作;
  4. [],空对象,和上面的步骤结合起来就是:

    undefined + []

    相加操作会把操作符两边的操作数通过ToPrimitive抽象操作转化为原始数据类型,也就是[]会变为""

    undefined + ""

    相加操作的抽象步骤中,如果有一个操作数是字符串,会调用ToString抽象操作把两个操作数都转化为字符串类型,也就是:

    undefined + "" // => "undefined" + "" => "undefined"

综上,([][[]]+[])的结果就是字符串"undefined"

[+!![]]

  1. !![],表示把一个数据转化为布尔类型,因为[]是一个真值,所以!![]的结果是true
  2. +!![],表示把前面的结果转化为数字类型,也就是+truetrue转化为数字是1,所以+!![]的结果是1
  3. [+!![]],也就是[1],结合第一部分([][[]]+[])的结果:

    ([][[]]+[])[+!![]] // => "undefined"[1] => 也就是获取字符串"undefined"的第二个字符,也就是"n" => "n"

([]+{})

相加操作会调用ToPrimitive抽象操作把操作符两边的数据转化为原始数据类型,也就是:

([]+{}) // => "" + "[object Object]" // => "[object Object]"

[!+[]+!![]]

  1. +[],把数组转化为数字:

    +[] // => +"" => 0
  2. !+[],也就是!0true
  3. !![]true
  4. !+[]+!![],也就是true + true,又是相加操作,因为操作符两边都是布尔类型,所以会转化为数字类型,也就是1 + 1,也就是2

第三部分和第四部分的结果结合起来就是:

([]+{})[!+[]+!![]] // => "[object Object]"[2] => 也就是取字符串"[object Object]"的第三个字符,也就是"b" => "b"

第一二部分和第三四部分结合起来的结果就是:

([][[]]+[])[+!![]]+([]+{})[!+[]+!![]] // => "n" + "b" => "nb"

总结

希望大家看的开心!如果本文有什么错误或者不严谨的地方,欢迎在评论区留言。


luckness
6.2k 声望5.1k 粉丝