1. 类型转换
JavaScript数据类型转换有自动转换和强制转换两种类型。
其中JS提供了以下函数进行强制类型转换:
转换为数值类型:Number(mix)、parseInt(string,radix)、parseFloat(string)
转换为字符串类型:toString(radix)、String(mix)
转换为布尔类型:Boolean(mix)
2 强制转换
1.Number(mix) 可以将任意类型的参数mix转为数值类型,遵循相应的转换规则。
- 部分类型转换如下代码所示:
// 数值:转换后还是原来的值
Number(324) // 324
// 字符串:如果可以被解析为数值,则转换为相应的数值
Number('324') // 324
// 字符串:如果不可以被解析为数值,返回 NaN
Number('324abc') // NaN
// 空字符串转为0
Number('') // 0
// 布尔值:true 转成 1,false 转成 0
Number(true) // 1
Number(false) // 0
// undefined:转成 NaN
Number(undefined) // NaN
// null:转成0
Number(null) // 0
//如果参数是 Date 对象,Number() 返回从 1970 年 1 月 1 日至今的毫秒数
Number(new Date()) //1574938020867
- 关于字符串,遵循以下规则:
1. 只包含数字,则将其转换为十进制(忽略前导0)
2. 包含有效的浮点格式,转换为浮点数值(忽略前导0)如:Number("070"); // 70
3. 空字符串,转换为0 即:Number(""); //0
4.包含非以上格式,转换为NaN 如:Number("hello!"); // NaN
- 转换对象:
Number方法的参数是对象时,将返回NaN,除非是包含单个数值的数组:
Number({a: 1}) // NaN
Number([1, 2, 3]) // NaN
Number([5]) // 5
Number(['1']) // 1
Number([]) // 0
在进行Number转化时如下示例,Number函数将obj对象转为数值,首先会调用obj.valueOf方法, 结果返回对象本身;于是,继续调用obj.toString方法,这时返回字符串[object Object],对这个字符串使用Number函数,得到NaN。
var obj = {x: 1};
Number(obj) // NaN
// 等同于
if (typeof obj.valueOf() === 'object') {
Number(obj.toString());
} else {
Number(obj.valueOf());
}
(如果toString方法返回的不是原始类型的值,结果就会报错。)
1.2 parseInt(string, radix)函数,将字符串转换为整数类型的数值。它也有一定的规则:
(1)忽略字符串前面的空格,直至找到第一个非空字符 如:
parseInt("020dd"); // 20
(2)第一个字符不是数字符号或者负号,返回NaN 如:parseInt("hello!"); // NaN parseInt(""); //空字符串同样返回 NaN
(3)第一个字符是数字,则继续解析直至字符串解析完毕或者遇到一个非数字符号为止
(4)以0开头,当作八进制来解析;0x开头,当作十六进制来解析
如:parseInt("020dd"); // 20 parseInt("0x22d");//557
(5)如果指定radix参数,则以radix为基数进行解析 (radix表示要解析的数字的基数。介于 2 ~ 36 之间,如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN。)
1.3 parseFloat(string)函数,将字符串转换为浮点数类型的数值:
它的规则与parseInt基本相同,但也有点区别:字符串中第一个小数点符号是有效的,另外parseFloat会忽略所有前导0,如果字符串包含一个可解析为整数的数,则返回整数值而不是浮点数值。
- Number函数将字符串转为数值,要比parseInt函数严格很多。基本上,只要有一个字符无法转成数值,整个字符串就会被转为NaN。parseInt和Number函数都会自动过滤一个字符串前导和后缀的空格。
2.String(radix)方法,除undefined和null之外的所有类型的值都具有String()方法,其作用是返回对象的字符串表示:
//将 Array 的元素转换为字符串。结果字符串由逗号分隔,且连接起来。
String([1,2,4]) //"1,2,4"
// 如果 Boolean 值是 true,则返回 “true”。否则,返回 “false”
String(true) // "true"
// 返回日期的文字表示法
String(new Date()) // "Thu Nov 29 2019 17:24:11 GMT+0800 (中国标准时间)"
//返回数字的文字表示
String(2) // "2"
- String方法的参数如果是对象,返回一个类型字符串;如果是数组,返回该数组的字符串形式,相当于调用数组的Array.prototype.join()方法。
String({a: 1}) // "[object Object]"
// 空数组[]转为空字符串
String([]) // ''
String([1, 2, 3]) // "1,2,3"
// 数组中的null或undefined,会被当做空字符串处理
String([1, undefined, 3]) // '1,,3'
2.2 toString(radix)方法
toString()可以将数据都转为字符串,但是null和undefined不可以转换,toString()括号中可以写数字,代表进制,String()可以将null和undefined转换为字符串,但是没法转进制字符串。
3.Boolean(mix)函数,将任何类型的值转换为布尔值。
以下值会被转换为false:false、”"、0、NaN、null、undefined,其余任何值都会被转换为true。
2 自动转换
自动转换是以强制转换为基础的。遇到以下三种情况时,JavaScript 会自动转换数据类型:
(1)不同类型的数据互相运算 123 + 'abc' // "123abc"
(2)对非布尔值类型的数据求布尔值 if ('abc') { console.log('hello') } // "hello"
(3)对非数值类型的值使用一元运算符(即+和-)+ {foo: 'bar'} // NaN
- [1, 2, 3] // NaN
自动转换时预期什么类型的值,就调用该类型的转换函数。比如,某个位置预期为字符串,就调用String函数进行转换。如果该位置即可以是字符串,也可能是数值,那么默认转为数值。
3 使用场景
用于检测是否为非数值的函数:isNaN(mix)
在业务中经常遇到对后台返回值或用户输入值进行类型判断,再进行数值类的进一步操作,isNaN会尝试将参数值用Number()进行转换,“非数值”返回true,数值类型会返回false。逻辑操作符(!、&&、||)
(1)逻辑非(!)操作符首先通过Boolean()函数将它的操作值转换为布尔值,然后求反。
!'yes' //false
!0 //true
!null //true
!undefined //true
!NaN //true
!false //true
(2)逻辑与(&&)操作符,如果一个操作值不是布尔值时,遵循以下规则进行转换:
如果第一个操作数经Boolean()转换后为true,则返回第二个操作值,否则返回第一个值(不是Boolean()转换后的值)。示例如下:
console.log( 1 && 2); // 2
console.log( 1 && 0); // 0
console.log( 0 && 1); // 0
console.log( 0 && ''); // 0
总结即只要 "&&" 前面false,结果都返回 "&&" 前面的值;只要 "&&" 前面true,结果都返回 "&&" 后面的值。
另外,如果有一个值为null、NaN、undefined,结果均返回其本身null、NaN、undefined。
(3) 逻辑或(||)操作符,如果一个操作值不是布尔值,遵循以下规则:
如果第一个操作值经Boolean()转换后为false,则返回第二个操作值,否则返回第一个操作值;对于undefined、null和NaN的处理规则与逻辑与(&&)相同。
console.log( 1 || 2); // 1
console.log( 1 || 0); // 1
console.log( 0 || 1); // 1
console.log( 0 || '') //
console.log( 0 || 'NaN') // NaN
总结即只要"||"前面true,结果都返回"||"前面的值;只要"||"前面false,结果都返回"||"后面的值。
- 关系操作符(<, >, <=, >=)
(1)两个数值,进行数值比较
(2)两个字符串,比较字符串对应的字符编码值
(3)如果只有一个操作值是数值,则将另一个操作值转换为数值,进行数值比较
(4)如果一个操作数是对象,则调用valueOf()方法(如果对象没有valueOf()方法则调用toString()方法),得到的结果按照前面的规则执行比较
(5)如果一个操作值是布尔值,则将其转换为数值,再进行比较
注:NaN是非常特殊的值,它不和任何类型的值相等,包括它自己,同时它与任何类型的值比较大小时都返回false。
- 相等操作符(==)相等操作符会对操作值进行隐式转换后进行比较:
//如果一个操作值为布尔值,则在比较之前先将其转换为数值
true ==1 // true
//如果一个操作值为字符串,另一个操作值为数值,则通过Number()函数将字符串转换为数值
'23' == 23 // true
//null与undefined是相等的
null == undefined // true
//如果一个操作值是对象,另一个不是,则调用对象的valueOf()方法,得到的结果按照前面的规则进行比较
//如果一个操作值为NaN,则相等比较返回false
Number('2ds') == NaN // false
//如果两个操作值都是对象,则比较它们是不是指向同一个对象
4 总结
在日常开发中有非常多数据类型转换的场景,通过数据类型转换能够避免一些处理操作错误、多种类型数据判断。
valueOf()方法和toString()方法会在不同的场景被调用,进而得到相应的返回值,最后根据返回值再进行类型转换,将其转为目标类型。
由于自动转换具有不确定性,而且不易除错,在预期为布尔值、数值、字符串的地方,建议使用Boolean、Number和String函数进行显式转换。