JS 隐式转换


今天在复习隐式转换的时候发现了一些盲点,首先简要回顾一下隐式转换规则。

+

加号,既可以是算术运算符,也可以是字符串连接符,规则为:

  • 只要有一边是字符串,则是字符串连接符
  • 两边都是数字,才是算术运算符

如果是其他类型,则调用相应的toString和Number()方法转换得到可运算的值。
一些特殊的toString和Number转换结果:
{ 1: 2 } // “[object Object]” NaN
[1, 2] // “1,2” NaN
function fn(){} // function函数体 NaN
undefined、null、true、false,toString均为本身的字符串,Number结果分别为NaN、0、1、0

1 + 'true' // "1true"
1 + true // 2

以上就是之前我对+隐式转换的了解,特殊类型+数字用Number,特殊类型+字符串用toString。

不过今天乱组合的时候发现了这样的情况

alert + ''
// "function alert() { [native code] }"
alert + 1
// "function alert() { [native code] }1"
[1, 2] + ''
// "1,2"
[1, 2] + 1
// "1,21"

function和array在+运算时只会进行字符串拼接操作。

{} + ''
// 0
'' + {}
// "[object Object]"
{} + 1
// 1
1 + {}
// "1[object Object]"

当{}在左边时,+总会被当成算术运算;当{}在右边时,+总会被当成字符串连接;无论另一边是什么类型。
这两个新规则也算是新盲点get。

隐式转换其他规则:

关系运算符

只有一边是string,将其他数据类型用Number进行转换再比较;
当两边都是string,比较其Unicode编码,string.charCodeAt;
如果是多字符,则依次比较:

2 > '10' // false 转成数字 2 > 10
'2' > '10' // true 都是字符串,比较'2'和'1'的Unicode编码
'abc' > 'aad' // 第一位相等,比较第二位,'b' > 'a',所以true

复杂数据类型

也就是最开始提到的对象、数组计算,规则是:
先用valueOf获取其原始值,如果不是Number类型(一般都不是,除非改写),则调用toString转成字符串,再转成number。转成什么类型视操作符及另一端决定。
经典题目:

if (a == 1 && a == 2 && a == 3) {
    console.log('amazing')
}
// a = ?

// answer
a = {
    i: 0,
    valueOf: function() {
        return ++a.i
    }
}

这些也只是作为了解,知道复杂数据类型在隐式转换的过程中经历了哪些操作。

==

  • !是Boolean()格式化比较,只要出现了,就都要转成布尔值比较。
  • 都是引用类型,比较地址

[] 和 {} 转换结果都是true

[] == 0 // true 根据toString的结果,[]->"",Number("") -> 0 == 0
![] == 0 // true ![]->false == 0
[] == ![] // true []->""->0 == false<-![]
[] == [] // false 比较地址
{} == !{} // false {}->"[object Object]" != !{}->false
{} == {} // false 比较地址

学习隐式转换并不是在开发中偷工减料,而是防止误操作,以及了解这些原理能够更好地纠错。


文章作者: kinoko
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 kinoko !
  目录