[TOC]
数据类型转换
1. 概述
JavaScript是一种动态类型语言,变量没有类型限制,可以随时赋予任何值。
变量的类型无法再编译阶段确定,必须要在运行时才能知道。
虽然变量类型不确定,但各种运算符对数据类型是有要求的,如果运算符发现变量的类型与预期不符,就会自动转换类型。比如减法运算符期望左右两侧的变量是数值,如果不是就会自动将他们转换为数值:
'250' - '50' // 200
2. 强制转换(显示转换)
主要使用Number(obj)
、String(obj)
、Boolean(obj)
三个函数,手动将其他类型的变量转换为数字、字符串、布尔值。
2.1 强转数字的规则:Number(obj)
参数类型 | 转为数值的规则 | 举例 |
---|---|---|
Number | 不变 | Number(123) => 123 |
String | 如果可以被解析,转为相应数值,否则为NaN,空串和空白符( 空格、制表符、换页符和换行符)转为0 | '123' => 123, '12ab' => NaN, '' =>0, '\n' => 0 |
Boolean | true:1,false:0 | true => 1, false => 0 |
undefined | 转为 NaN | undefined => NaN |
null | 转为0 | null => 0 |
Object | 转为NaN,但:包含单个数值的数组会返回对应数值 | {} => NaN, [1] => 1, |
Number(obj) 函数介绍:将其他类型的值转化成数字。Number函数整体转换,有一个无法转换就会返回NaN。参数(obj):待转换的值。
Number()
关于对象的转换规则:
- 调用对象自身的
valueOf
方法,如果返回原始类型的值,则直接使用Number函数,结束- 如果
valueOf
方法返回的还是对象,则调用对象的toString
方法,如果返回原始类型的值,则直接使用Number函数,结束- 如果
toSrting
方法返回的是对象,就报异常(Uncaught TypeError: 对象不能转为原始类型),结束
var obj = {
valueOf: function () { return {}; },
toString: function () { return {}; }
};
Number(obj) // Uncaught TypeError: Cannot convert object to primitive value
2.2 强转字符串规则:String(obj)
参数类型 | 返回结果 | 举例 |
---|---|---|
Number | 转为相应的字符串 | String(123) => "123" |
String | 不变 | String('abc') => "abc" |
Boolean | true: "true", false: "false" | String(true) => "true" |
undefined | "undefined" | String(undefined) => "undefined" |
null | " null" | String(null) => "null" |
Object | {a: 1} : "[object Object]", 数组: 数组的字符串形式 | String([1, 2, 3]) => "1, 2, 3" |
NaN | "NaN" | String(NaN) => "NaN" |
1、String()函数可以将任意类型的值转化成字符串。参数: 待转换的值。
String()
关于对象的转换规则:
- 先调用对象的toString方法,如果返回原始类型的值,则调用String函数,结束
- 如果toString方法返回的是对象,再调用对象的valueOf方法,如果返回原始类型的值,则调用String函数,结束。
- 如果valueOf方法返回的是对象,就报异常(Uncaught TypeError: 对象不能转为原始类型),结束
var obj = {
valueOf: function () { return {}; },
toString: function () { return {}; }
};
String(obj) // Uncaught TypeError: Cannot convert object to primitive value
2、其他类型转为字符串的方法
1、"" + value
2、value.toString()
2.3 强转布尔规则:Boolean(obj)
值 | 转换结果 |
---|---|
undefined | false |
null | false |
0(-0,+0) | false |
NaN | false |
''(空字符串) | false |
所有对象(包括空对象)(new Boolean(false)) | true |
其他 | true |
Boolean(obj)函数可以将任意类型的值转为布尔值。
所有对象的布尔值都是true,这是JavaScript出于性能的考虑,统一规定,如:obj1 && obj2
// 浏览器打开开发者工具, Console里面测试
Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean(NaN) // false
Boolean('') // false
Boolean({}) // true
Boolean([]) // true
Boolean(new Boolean(false)) // true
3. 自动类型转换(隐式转换)
自动转换是以强制转换为基础的,JavaScript会自动转换数据类型。
3.1 出现自动类型转换的情况
- 比较运算(
==
、!=
、>
、<
) if
、while
、三元运算符等需要布尔值地方- 算术运算(
+
、-
、*
、/
、%
) - 一元运算符(+,-)
123 + 'abc' // "123abc"
if ('abc') {}
+ {foo: 'bar'}
- [1, 2, 3]
'123' == 1
3.2 自动转换为布尔值
JavaScript遇到期望布尔值的时候(如if
、while
、三元运算符语句),就会将非布尔值的参数转为布尔值,系统自动调用Boolean函数。
if (!undefined) {} // if语句会转换成布尔值
expression ? true : false // 三元表达式会转换成布尔值
!! expression // 需要转换成布尔值
3.3 自动转换为字符串
遇到期望为字符串的地方,就会将参数转为字符串,转换规则:先将复合类型的值转为原始类型的值,再将原始类型的值转为字符串。
当字符串与其他变量做加法运算的时候,如果变量不是字符串,变量就会转为字符串。
'5' + 1 // '51'
'5' + true // "5true"
'5' + false // "5false"
'5' + {} // "5[object Object]"
'5' + [] // "5"
'5' + function (){} // "5function (){}"
'5' + undefined // "5undefined"
'5' + null // "5null"
var obj = { width: '100' };
obj.width + 20 // "10020"
3.4 自动转换为数值
遇到期望为数值的地方,就会将参数自动转为数值,系统自动调用Number函数。
1、除加法运算符(+)有可能把变量转为字符串,其他运算符都会把变量自动转为数值:
'5' - '2' // 3
'5' * '2' // 10
true - 1 // 0
false - 1 // -1
'1' - 1 // 0
'5' * [] // 0
false / '5' // 0
'abc' - 1 // NaN
null + 1 // 1
undefined + 1 // NaN
2、一元运算符也会把运算子转成数值:
+'abc' // NaN
-'abc' // NaN
+true // 1
-false // 0
==
判断相等的转换规则
3.5 在使用==
判断相等的时候,如果两个值类型相等,那么执行严格相等判断,如果类型不同,则会自动做类型转换为相同然后在执行严格相等判断。
对于a == b
的比较规则:
类型 | 转换规则 |
---|---|
都是原始类型的值 | 转换成Number再进行比较 |
对象与原始类型的值 | 对象转化成原始类型的值,再进行比较。 |
undefined 和 null | 与其他类型的值比较时,结果都为false ,它们互相比较时结果为true |
对象与对象 | 比较的是对象的引用地址,两个不同对象永远不会相等 |
存在NaN | 返回false |
1 == true // true 等同于 1 === Number(true)
2 == true // false 等同于 2 === Number(true)
'true' == true // false 等同于 Number('true') === Number(true) => NaN === 1
'' == 0 // true 等同于 Number('') === 0
'' == false // true 等同于 Number('') === Number(false)
'\n 123 \t' == 123 // true
[1] == 1 // true 等同于 Number([1]) == 1
[1] == '1' // true 等同于 Number([1]) == Number('1')
[1] == true // true 等同于 Number([1]) == Number(true)
false == undefined // false
0 == undefined // false
undefined == null // true
var a = {}, b = {}, c = b
a == b // false
c == b // true
NaN == 1 // false
NaN == NaN // false
使用==
判断会带来一些违反直觉的结果,所以一些JS规范会强制使用===
来做判断。
0 == '0' // true
0 == '' // true
2 == true // false
2 == false // false
false == 'false' // false
false == '0' // true
false == undefined // false
false == null // false
null == undefined // true
' \t\r\n ' == 0 // true
详细:相等运算符 阮一峰
4. 强制转为数字的其他方法:parseInt()、parseFloat()
Number函数整体转换,parseInt和parseFloat则是逐个解析字符。
4.1 parseInt(string, radix)
parseInt(string, radix) :函数将其第一个参数转换为一个字符串,对该字符串进行解析,然后返回指定基数的十进制整数或 NaN
。 radix
是2-36之间的整数,表示被解析字符串的基数。第二个参数可不传,默认值为10,即默认是十进制转十进制。
参数:
string:要被解析的值。如果参数不是一个字符串,则将其转换为字符串 (使用 ToString
抽象操作)。字符串开头的空白符将会被忽略。
radix:从2到36之间的整数值,表示进制的基数。例如指定 16
表示被解析值是十六进制数。如果超出这个范围,将返回 NaN
。
关于radix参数:
若传递的是0、NaN、undefined,则分两种情况: 1、若string以“0x”或“0X”开头,则默认为16进制 2、若不是第一种情况则会10进制
若进制小于2或者大于36,就会输出NaN
若是2-36,而string是无效数字,则转为NaN
转换结果:
- 如果输入的参数无法转化为数值类型,则返回NaN, 空字符串也返回NaN。
- 字符串的开头的空白字符会被忽略,直到找到第一个非空白字符开始转换。
- 从第一个字符开始,直到遇到非数字字符或结尾结束,返回解析的整数部分,非数字部分忽略。
- 如果设置了第二个参数,表示被解析的值的进制(二进制、十进制、十六进制),返回该值对应的十进制数。
parseInt(" \n132.44ddd"); // 132
parseInt("0xF", 16); // 15
parseInt("0xF"); // 15:默认返回十进制的解析
parseInt(''); // NaN
parseInt("546", 2); // Nan , 除了“0、1”外,其它数字都不是有效二进制数字
arseInt(" \nddd"); // NaN
4.2 parseFloat(string)
介绍:把字符串解析为浮点数并返回,parseFloat是个全局函数,不属于任何对象.
参数:
String:需要解析的字符串
转换结果:
- 如果参数不能解析成数字,则返回NaN,parseFloat只能返回十进制数
- 如果遇到了与浮点数无关的字符,则函数停止解析,返回已经解析到的浮点数,
- 字符串的头部空白字符会被忽略
- 如果字符串没有小数点或小数点后都是零,则返回整数,字符串中第一个出现的小数点是有效的。第二小数点则被解析成非数字。
- 与浮点数相关的字符:正负号(+或-),数字(0-9),小数点,或者科学记数法中的指数(e或E)
parseFloat(''); // NaN
parseFloat('\n 32.14dsad'); // 32.14
parseFloat(' 123.00000dad'); // 123
parseFloat("0.0314E+2"); // 3.14
parseFloat(' \n .12345'); // 0.12345
parseFloat(' \n .12.345'); // 0.12
rseFloat('dsss') // NaN