在javascript中隐式类型转换总是返回基本类型值,如字符串、数字、布尔值,不会返回对象或者函数。所以我们在介绍隐式类型转换之前首先来看一看字符串、数字、布尔值之间类型转换的基本规则。这里涉及到ToString
、ToNumber
和ToBoolean
,同时我们还会介绍ToPrimitive
。
一、抽象值操作
(一)ToString
ToString
负责处理非字符串到字符串的强制类型转换。
(1)基本类型的值转化为字符串的基本规则:
1. null转化为"null"
2. undefined转化为"undefined"
3. true转化为"true"
4. 数字的字符串转化规则遵循通用规则,不过那些极小或者极大的数值使用指数形式:
var a = 1.07 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000
a.toString() // "1.07e21"
(2)对于普通对象来说,如果没有自定义toString()
方法,返回"[object Object]"
。如果有自己的toString()
方法就会调用该方法并返回值。
(3)数组的toString()
返回所有单元字符串化以后再用”,”连接起来:
var a = [1,2,3]
a.toString() // “1,2,3”
(4)日期、正则、函数也遵循通用规则。
(二)ToNumber
(1)基本类型的值转化为数字的基本规则:
1. null转化为0
2. undefined转化为NaN
3. true转化为1,false转化为0
4. 字符串的处理遵循通用规则
Number("23") // 23
Number("") // 0
(2)对象或者数组首先会被转化为相应的基本类型,如果返回的是非数字的基本类型,再按照以上规则进行转化。其中对象转化为基本类型的时候会使用ToPrimitive
操作。
(三)ToPrimitive
ToPrimitive
操作会首先检查对象是否有valueOf()
方法,如果有并且返回基本类型的值,就调用该方法进行类型转化。如果没有就使用toString()
返回的值。
如果valueOf()
和toString()
均不返回基本类型的值,就会产生TypeError
错误。
如果不对对象和数组的valueOf()
和toString()
方法进行重写,那么:
(1)对象的valueOf()
返回对象本身,toString()
返回"[object Object]"
(2)数组的valueOf()
返回数组本身,toString()
返回所有单元字符串化以后再用”,”连接起来。
1
2
3
4
5
6
7
8
9
var a = {
name: 'sillywa'
}
var b = [1,2,3]
a.valueOf() // { name: 'sillywa' }
a.toString() // "[object Object]"
b.valueOf() // [1,2,3]
b.toString() // "1,2,3"
(四)ToBoolean
null
转化为false
1 | Boolean(null) // false |
undefined
转化为false
1
Boolean(undefined) // false
- 除””以外,所有字符串转化为
true
1
2
3Boolean("") // fasle
Boolean("abc") // true
Boolean('0') // true - 除0(包括+0和-0)和
NaN
外,所有数字转化为true
1
2
3Boolean(0) // false
Boolean(NaN) // false
Boolean(-9) // true - 所有对象转化为
true
1
2
3
4
5
6
7
8
9Boolean({}) // true
Boolean([]) // true
// 需要注意的是通过new关键字得到的是一个对象
var a = new Boolean(false)
var b = new Number(0)
var c = new String('')
var d = Boolean(a && b && c)
d // true二、隐式类型转化
(一)字符串和数字之间的隐式类型转化
(1)数字转化为字符串
+运算符既能用于数字相加,也能用于字符串拼接。那么javascript是怎么判断我们要执行那个操作的呢?例如:
1 | var a = '42' |
以上代码不难理解,通常我们认为+运算符两边只要有一个操作数是字符串就会执行字符串的拼接操作,但是实际情况更为复杂,例如:
1 | var a = [1,2] |
a,b
都不是字符串,但是它们都被转化为字符串进行拼接操作,原因何在?
简单的理解应当是如果+运算符其中一个是字符串或者可以通过ToPrimitive
(针对于对象,包括数组)转化为字符串,则执行字符串的拼接;否则执行数字相加。
需要注意的是如果是 + '42'
代表强制类型转化为数字,即 42
。
(2)字符串转化为数字
- , * , /都可以用来将字符串转化为数字,其规则与+类似
1 | var a = '3.14' |
同样对于对象和数组也是一样
1 | var a = [2] |
为了执行减法运算,a、b
都需要被转化为数字,首先通过ToPrimitive
转化为字符串再转化为数字。
(二)布尔值到数字的隐式类型转化
简单举了例子:
1 | 1 + false // 1 |
(三)隐式类型转化为布尔值
以下几种情况会发生隐式类型转化为布尔值
if(..)
条件判断语句for()
中的条件判断while()
和do..while(..)
中的条件判断? :
三目运算符中的条件判断- 逻辑运算符
||
和&&
左边的操作数
(四)|| 和 &&
ES5规范中有如下描述
&&
和||
运算符并不一定返回布尔值,而是两个操作数其中一个的值
例如:
1 | var a = 42 |
|| 和 &&
首先会对第一个操作数进行条件判断,如果其不是布尔值,会被转化为布尔值,在进行判断。
对于 ||
如果第一个操作数返回true则返回第一个操作数的值,如果第一个操作数返回false就返回第二个操作数的值。
对于 &&
如果第一个操作数返回true则返回第二个操作数的值,如果第一个操作数返回false就返回第一个操作数的值。
本篇就介绍到这里,下篇介绍隐式类型转换之(宽松相等和严格相等)。