丧心病狂的js面试题
1 |
|
这算不上是一道好的面试题。虽然我认为这样的面试题不值得提倡,但是知识点还是要掌握。
拆解问题
把打印的表达式拆分成++[[]][+[]]
、 +
、 [+[]]
三部分。注意这不是随意地拆分,是根据JavaScript表达式及运算符号优先级进行拆分的。同样地,将拆分后得到地表达式按照同样的方法逐步拆分运算。
step 1
先来看第一部分++[[]][+[]]
继续拆分 ++
[[]]
[+[]]
[[]]
,这是一个数组,数组只有一个元素,这个元素是一个空数组[]
。- 然后来看
[+[]]
,这也是一个数组,数组只有一个元素。运算后得到[0]
- 组合
[[]][+[]]
得到[[]][0]
,意思是取得数组[[]]
的第0个元素,运算结果为[]
++[]
运算结果就是数字类型的值1
step 2
再来看第三部分[+[]]
运算过程在step 1
已经分析过了,运算后结果为[0]
。
step 3
然后把+
前后的运算结果组合起来1 + [0]
,结果为字符传类型的"10"
。
计算过程
前面简单说明了表达式拆分及计算结果,现在来详细解释一下JavaScript中运算符的类型转换规则及取值过程。
计算 [+[]]
- 来看
[+[]]
中+[]
的计算。+[]
意思是把数据(这里是一个空数组)转换成数字 - 这个转换过程就是JavaScript尝试取得原始值。
[]
首先调用[].valueOf()
,还是得到[]
- 由于上一步未取得原始值,继续调用
[].toString()
,得到""
。空字符串是原始值 - 继续调用
+""
。在表达式+''
中,''
是一个空字符串。当+
运算符应用于一个空字符串时,它会将空字符串转换为数字。根据JavaScript的类型转换规则,一个空字符串在转换为数字时会被解释为0。因此,+''
的结果是数字类型的值0。 [+[]]
的运算结果就是[0]
计算 ++[]
这里提一下,++
自增运算符只能应用于变量或对象的属性,而不能直接应用于字面量或表达式。
++[]
在自增之前首先要取得[]
的原始值[]
的原始值运算过程前面已经介绍过了,[]
的原始值运算结果是空字符串""
- 继续计算
+""
,这个跟前面也是一样的。运算结果为数字类型的0
++[]
就是计算++0
,0自增1后得到数字类型1。
计算 1 + [0]
- 这个表达是首先会尝试取得
[0]
的原始值 - 首先调用
[0].valueOf()
,运算结果还是数组[0]
- 继续调用
[0].toString()
,得到 字符串类型"0"
- 最后计算
1 + "0"
得到字符串"10"
总结
这道题考察了JavaScript语言的运算符优先级规则、类型转换规则、各种数据类型数据转换成原始值的方法(拆箱)。
参考
- JavaScript运算符优先级
- 常见的类型转换规则:
字符串转换:当一个值与字符串进行操作时(例如使用+运算符连接字符串),JavaScript会将该值转换为字符串类型。这种转换称为字符串转换。
数字转换:当一个值与数字进行操作时(例如使用+运算符进行加法运算),JavaScript会将该值转换为数字类型。这种转换称为数字转换。
布尔转换:在需要布尔值的上下文中,JavaScript会将值转换为布尔类型。以下值会被转换为false:false、null、undefined、0、NaN和空字符串 ‘’。其他所有值都会被转换为true。
对象转换:当一个非原始值(例如对象、数组)与字符串或数字进行操作时,JavaScript会尝试将其转换为相应的原始类型。这种转换称为对象转换。对象转换通常通过调用对象的toString()或valueOf()方法来完成。
显式类型转换:JavaScript提供了一些内置函数来进行显式的类型转换。例如,Number()函数可以将值转换为数字类型,String()函数可以将值转换为字符串类型,Boolean()函数可以将值转换为布尔类型。
需要注意的是,类型转换可能会导致意外的结果。在进行类型转换时,应该注意数据的原始类型,并确保转换结果符合预期