从一道题看js的拆箱操作
程序员文章站
2022-06-20 08:32:35
前段时间看到一道题,如下:([][[]]+[])[+!![]]+([]+{})[!+[]+!![]]问最终打印结果,然后简单了解一下js的装箱,拆箱操作。 基本 1. 装箱操作: 就是将基本类型(String, Number, Boolean)转为引用类型 2. 拆箱操作: 与装箱相反,就是将引用类 ......
前段时间看到一道题,如下:([][[]]+[])[+![]]+([]+{})[!+[]+![]]问最终打印结果,然后简单了解一下js的装箱,拆箱操作。
基本
- 装箱操作: 就是将基本类型(string, number, boolean)转为引用类型
- 拆箱操作: 与装箱相反,就是将引用类型转为基本类型, 常用的基本方法有: valueof , tostring()
分析
像上面的那个题目,主要是拆箱操作,下面就来简单拆解分析一下吧:
1. 基础: [] ==> [] (array); [[]] ==> [array(0)] (array); []+[[]] ??? ok, 我们简单来了解一下js中的+运算符: +:一般是用于对象相加的,这是在两个对象都是number的情况下。那其他类型下就涉及到隐式转换,下面看下隐式转换的规则 1. 如果一个对象是string,那么就要将另一个对象转换为string再进行字符串拼接 2. 如果对象都是复杂类型,那么就要将两个对象均转化为string,再进行拼接。 至于如果对象是其他简单类型(number, boolean),就要先将对象转化为number再进行运算 所以 []+[[]] ==> string([]) + string([[]]) == "" + "" ==> "" 2. 拆解: 然后我们来看下题目,简单拆分为4部分: 1. ([][[]]+[]) [][[]] 这部分乍一眼看过去会觉得很蒙,但我们已经知道[] ==> array,常用的获取array中的数据的方法有array[] 所以,让我们来拆解下吧: 首先为了更清楚,将最左侧的[]赋值给 father ==> var father = []; 将右侧[]中的[]赋值给child ==> var child = []; 即最终 [][[]] == father[child] == "undefined" [][[]] + [] == string("undefined") + string([]) == "undefined" 2. [+!![]] 关于这一部分,我们需要了解一下!! !!: 一般来说,似乎大家普遍认为是将对象取反,再取反,即双重否定。但其实应该是将对象强制转换为boolean类型。 关于boolean中,需要关注,{}和[]转换为boolean时是true. [+!![]] ==>[+true] ==> [number(true)] ==> [1] 3. ([]+{}) 这一部分就很简单了: []+{} ==> string([]) + string({}) == "" + "[object object]". 但是,如果将上面两个对象调转位置呢: {} + [] : 按常规来说,应该是和上面一样的结果,但是最终的打印结果却是0,这是为什么呢。 js中{} 不仅可以代表一个对象,同时也有可能是一个代码块,有些时候,js会将写在前面的{}解释为代码块,于是参与运算的其实就只有+[]了。 4. [!+[]+!![]] 经过上面部分,这里也很清楚了: !+[] ==> ! + string([]) == !+"" == !"" == true [true + !![]] == [true + true] = [number(true) + number(true)] == [2] 所以最后的结果: "undefined"[1] + "[object object]"[2] == "nb";
通过上面的题目,应该已经大致了解了关于拆箱的一些基础了。这样,下次看到就不会一头雾水了。
推荐阅读