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