类型转换
JS 中有六种简单数据类型:
undefined
、null
、boolean
、string
、number
、symbol
,以及一种复杂类型:object
同类型可以运算的, 不同类型之间(转换之后)能运算的
JavaScript 是一种动态类型语言,变量没有类型限制,可以随时赋予任意值。
js
let y = true;
let x = y ? 1 : "tian好帅";
console.log(x);
//变量x到底是数值还是字符串,取决于另一个变量y的值
//y为true时,x是一个数值 y为false时,x是一个字符串
//x的类型没法在编译阶段就知道 必须等到运行时才能知道
虽然变量的数据类型是不确定的,但是各种运算符对数据类型是有要求的。
如果运算符发现,运算子的类型与预期不符就,会自动转换类型。
比如,减法运算符预期左右两侧的运算子应该是数值,如果不是,就会自动将它们转为数值。
js
console.log("10" - "4");//6
//上面代码中,虽然是两个字符串相减,但是依然会得到结果数值1,
//原因就在于 JavaScript 将运算子自动转为了数值。
显式类型转换
强制转换主要指使用
Number()
、String()
和Boolean()
三个函数,手动将各种类型的值,分别转换成数字、字符串或者布尔值。toString()
String()
Number()
parseInt(string)
parseFloat(string)
Boolean()
有3个函数可以把非数值转换为数值:
Number()
parseInt()
parseFloat()
parseInt()和parseFloat()
专门用于把字符串转换成数值。
parseInt()
parseInt
方法用于将字符串转为整数。
js
console.log(parseInt('666')); //666
如果parseInt
的参数不是字符串,则会先转为字符串再转换。
js
console.log(parseInt(3.14)); //3
// 等同于
console.log(parseInt("3.14")); // 3
parseInt()具有以下特性:
(1)只保留字符串最开头的数字,如果遇到不能转为数字的字符就不再进行下去,返回已经转好的部分
js
console.log(parseInt("2020在公众号上写了6篇文章")); //打印结果:2017
console.log(parseInt("2020.01在公众号上写了6篇文章")); //打印结果仍是:2017 (说明只会取整数)
console.log(parseInt("aaa2017.01在公众号上写了6篇文章")); //打印结果:NaN (因为不是以数字开头)
//如果字符串头部有空格,空格会被自动去除。忽略开始的空格
console.log(parseInt(' 666')); //666
console.log(parseInt('8a')); // 8
console.log(parseInt('12**')); // 12
console.log(parseInt('12.34')); // 12
console.log(parseInt('15e2')); // 15
console.log(parseInt('25px')); //25
(2)如果对非 String使用 parseInt()或 parseFloat(),它会先将其转换为 String 然后再操作。【重要】
js
let a = 168.23;
console.log(parseInt(a)); //打印结果:168 (因为是先将 a 转为字符串"168.23",然后然后再操作)
let b = true;
console.log(parseInt(b)); //打印结果:NaN (因为是先将 b 转为字符串"true",然后然后再操作)
let c = null;
console.log(parseInt(c)); //打印结果:NaN (因为是先将 c 转为字符串"null",然后然后再操作)
let d = undefined;
console.log(parseInt(d)); //打印结果:NaN (因为是先将 d 转为字符串"undefined",然后然后再操作)
(3)自动带有截断小数的功能:取整,不四舍五入。
js
let a = parseInt(5.8) + parseInt(4.7);
console.log(a);
打印结果:
css
9
如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回NaN
。
js
parseInt('abc') // NaN
parseInt('.3') // NaN
parseInt('') // NaN
parseInt('+') // NaN
parseInt('+1') // 1
//parseInt的返回值只有两种可能,要么是一个十进制整数,要么是NaN。
(4)进制转换 带两个参数时,表示在转换时,包含了进制转换。
第二个参数(2到36之间),表示被解析的值的进制,返回该值对应的十进制数。
默认情况下,
parseInt
的第二个参数为10,即默认是十进制转十进制。
js
parseInt('1000') // 1000
// 等同于
parseInt('1000', 10) // 1000
js
parseInt('1000', 2) // 8
parseInt('1000', 6) // 216
parseInt('1000', 8) // 512
//就是说,无论 parseInt() 里面的进制参数是多少,最终的转换结果是十进制。
js
let a = '5';
let num = parseInt(a, 2); // 将 a 当成 二进制 来看待,转换成 十进制 的 num
console.log(num); // 打印结果:NaN。因为 二进制中没有 5 这个数,转换失败。
如果第二个参数不是数值,会被自动转为一个整数。
这个整数只有在2到36之间,才能得到有意义的结果。
超出这个范围,则返回NaN
。
如果第二个参数是0
、undefined
和null
,则直接忽略。
js
parseInt('10', 37) // NaN
parseInt('10', 1) // NaN
parseInt('10', 0) // 10
parseInt('10', null) // 10
parseInt('10', undefined) // 10
parseFloat()
parseFloat
方法用于将一个字符串转为浮点数。parseFloat()和 parseInt()的作用类似,不同的是,parseFloat()可以获得有效的小数部分。
js
parseFloat('3.14'); // 3.14
如果字符串包含不能转为浮点数的字符,则不再进行往后转换,返回已经转好的部分。
js
parseFloat('3.14more non-digit characters') // 3.14
从第一个字符开始解析每个字符,直至遇见一个无效的浮点数字符为止,忽略第一个小数点后面的小数点。
js
let a = "12.34.56px";
console.log(parseFloat(a));// 12.34
如果参数不是字符串,或者字符串的第一个字符不能转化为浮点数,则返回NaN
。
js
parseFloat([]) // NaN
parseFloat('FF2') // NaN
parseFloat('') // NaN
parseFloat() 的几个特性,可以参照 parseInt()。
Number()
使用
Number
函数,可以将任意类型的值转化成数值。下面分成两种情况讨论,一种是参数是原始类型的值,另一种是参数是对象。
js
// 数值:转换后还是原来的值
Number(324); // 324
1.原始类型值
情况一:字符串 --> 数字
- 1.如果字符串中是纯数字,则直接将其转换为数字。
- 2.如果字符串是一个空串或者是一个全是空格的字符串,则转换为 0。
- 3.只要字符串中包含了其他非数字的内容(
小数点
按数字来算),则转换为 NaN。
js
// 字符串:如果可以被解析为数值,则转换为相应的数值
Number('324'); // 324
// 字符串:如果不可以被解析为数值,返回 NaN
Number('324abc'); // NaN
// 空字符串转为0
Number(''); // 0
情况二:布尔 --> 数字
- true 转成 1
- false 转成 0
js
// 布尔值:true 转成 1,false 转成 0
Number(true); // 1
Number(false); // 0
情况三:null --> 数字
- 结果为:0
js
// null:转成0
Number(null); // 0
情况四:undefined --> 数字
- 结果为:NaN
js
// undefined:转成 NaN
Number(undefined); // NaN
// 一定会返回一个数值, 不合理的转换就会显示: NaN
补充:怎么理解这里的 NaN 呢?可以这样理解,使用 Number() 函数之后,如果无法转换为数字,就会转换为 NaN。
Number
函数将字符串转为数值,比parseInt
函数严格很多
只要有一个字符无法转成数值,整个字符串就会被转为NaN
。
js
parseInt('42 abc'); // 42
Number('42 abc'); // NaN
//parseInt逐个解析字符,而Number函数整体转换字符串的类型。
2.对象
js
Number({a: 1}) // NaN
Number([1, 2, 3]) // NaN
console.log(Number([])); //0
Number([5]) // 5
//Number方法的参数是对象时,将返回NaN 除非是包含单个数值的数组。
对象转数值的时候底层是调用了这个对象的toString方法
语法:
变量.toString()
【重要】该方法不会影响到原变量,它会将转换的结果返回。当然我们还可以直接写成a = a.toString()
,这样的话,就是直接修改原变量。
注意:null 和 undefined 这两个值没有 toString()方法,所以它们不能用方法二。如果调用,会报错。
另外,Number 类型的变量,在调用 toString()时,可以在方法中传递一个整数作为参数。此时它将会把数字转换为指定的进制,如果不指定则默认转换为 10 进制。例如:
js
var a = 255;
//对于Number调用toString()时可以在方法中传递一个整数作为参数
//此时它将会把数字转换为指定的进制,如果不指定则默认转换为10进制
a = a.toString(2); // 转换为二进制
console.log(a); // 11111111
console.log(typeof a); // string
js
let arr = [];
console.log(arr.toString()); //""
let arr = [6];
console.log(arr.toString()); //字符串6
let arr = [6 , 9];
console.log(arr.toString()); //字符串6,9
let obj = {};
console.log(obj.toString()); //[object Object] 所以再次调用number返回NaN
重写对象里面的toString方法
js
let obj = {
toString:function(){
return 123;
}
};
console.log(obj.toString());//字符串123
console.log(Number(obj));//数字123
Number() 函数和 parseInt() 函数的区别:
就拿
Number(true)
和parseInt(true)/parseFloat(true)
来举例,二者在使用时,是有区别的:
- Number(true) :千方百计地想转换为数字。
- parseInt(true)/parseFloat(true) :先转为字符串,再提取出最前面的数字部分;没提取出来,那就返回 NaN。
String()
String
函数可以将任意类型的值转化成字符串
1.原始类型值
数值:转为相应的字符串。
字符串:转换后还是原来的值。
布尔值:
true
转为字符串"true"
,false
转为字符串"false"
。undefined:转为字符串
"undefined"
。null:转为字符串
"null"
。
js
String(123); // "123"
String('abc'); // "abc"
String(true); // "true"
String(undefined); // "undefined"
String(null); // "null"
2.对象
String
方法的参数如果是对象,返回一个类型字符串 "[object Object]"
如果是数组,返回该数组的字符串形式。(去掉中括号, 左右两边加引号)
如果是函数: 直接原样复制 左右两边加引号.
js
String({a: 1}) // "[object Object]"
String([1, 2, 3]) // "1,2,3"
Boolean()
Boolean()
函数可以将任意类型的值转为布尔值。
除了以下六个值的转换结果为false
,其他的值全部为true
。
js
undefined
null
0
NaN
'' ""(空字符串)
false
js
Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean(NaN) // false
Boolean("") // false
Boolean(false) // false
隐式转换
自动转换,它是以强制转换为基础的。
遇到以下三种情况时,JavaScript 会自动转换数据类型,即转换是自动完成的,用户不可见。
第一种情况,不同类型的数据互相运算。
js
123 + 'abc' // "123abc";
第二种情况,对非布尔值类型的数据求布尔值。
js
if ('abc') {
console.log('hello')
} // "hello"
第三种情况,对非数值类型的值使用一元运算符(即+
和-
)。
js
+ {foo: 'bar'} // NaN
- [1, 2, 3] // NaN
自动转换的规则是这样的:
预期什么类型的值,就调用该类型的转换函数。
比如,某个位置预期为字符串,就调用
String
函数进行转换。如果该位置即可以是字符串,也可能是数值,那么默认转为数值。
由于自动转换具有不确定性,而且不易除错,建议在预期为布尔值、数值、字符串的地方,全部使用
Boolean
、Number
和String
函数进行显式转换。
自动转换为布尔值
JavaScript 遇到预期为布尔值的地方(比如
if
语句的条件部分),就会将非布尔值的参数自动转换为布尔值。系统内部会自动调用Boolean
函数。因此除了以下6个值,其他都是自动转为
true
。
js
undefined
null
0
NaN
'' ""(空字符串)
false
下面这个例子中,条件部分的每个值都相当于false
,使用否定运算符后,就变成了true
。
js
if ( !undefined && !null && !0 && !NaN && !'') {
console.log('true');
} // true
下面两种写法,有时也用于将一个表达式转为布尔值。它们内部调用的也是Boolean
函数。
js
// 写法一
expression ? true : false
// 写法二
!! expression
// !表达式 运算符: 取反
// !(!表达式) 表达式直接转布尔类型
自动转换为字符串
JavaScript 遇到预期为字符串的地方,就会将非字符串的值自动转为字符串
具体规则是,
先将复合类型的值转为原始类型的值,再将原始类型的值转为字符串。
字符串的自动转换,主要发生在字符串的加法运算时。
当一个值为字符串,另一个值为非字符串,则后者转为字符串。
js
'5' + 1 // '51'
'5' + true // "5true"
'5' + false // "5false"
'5' + {} // "5[object Object]"
'5' + [] // "5"
'5' + function (){} // "5function (){}"
'5' + undefined // "5undefined"
'5' + null // "5null"
这种自动转换很容易出错。
js
let obj = {
width: '100'
};
obj.width + 20 // "10020"
//上面代码中,开发者可能期望返回120,但是由于自动转换,实际上返回了一个字符10020
自动转换为数值
JavaScript 遇到预期为数值的地方,就会将参数值自动转换为数值。系统内部会自动调用
Number
函数。除了加法运算符(
+
)有可能把运算子转为字符串,其他运算符都会把运算子自动转成数值。自增/自减运算符:
++
、—-
正号/负号:
+a
、-a
加号:
+
运算符:
-
、*
、/
js
'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
//上面代码中,运算符两侧的运算子,都被转成了数值
//注意:null转为数值时为0,而undefined转为数值时为NaN。
一元运算符也会把运算子转成数值。
任何值做**
+a
、-a
**运算时,运算结果都会自动转换为 Number 类型。 内部调用的是 Number() 函数。
举例:
js
let a = '666';
let b = +a;
console.log(typeof a); // 打印结果:string。说明 a 的数据类型保持不变。
console.log(a); // 打印结果:666
console.log(typeof b); // 打印结果:number。说明 b 的数据类型发生了变化。
console.log(b); // 打印结果:666
js
console.log(+'abc'); // NaN
console.log(-'abc'); // NaN
console.log(+true); // 1
console.log(-false); // 0
内置对象 Number 的常见方法
Number.isInteger() 判断是否为整数
语法:
css
布尔值 = Number.isInteger(数字);
toFixed() 小数点后面保留多少位
css
字符串 = myNum.toFixed(num);
解释:将数字 myNum 的小数点后面保留 num 位小数(四舍五入),并返回。不会改变原数字。注意,返回结果是字符串。
参数 num:指定了小数点后面的位数。
举例:
js
let num = 3.456;
let num2 = num.toFixed(2);
console.log(num); // 打印结果:3.456
console.log(num2); // 打印结果:3.47
console.log(typeof num); // number
console.log(typeof num2); // string
上方代码中,num2
的结果是0.12,但是请注意,num
的类型Number型,而num
的类型却是String型。