JavaScript(三)数据类型的转换
一、概述
JavaScript 是一种动态类型语言,变量没有类型限制,可以随时赋予任意值var x = y ? 1 : 'a';
虽然变量的数据类型是不确定的,但是各种运算符对数据类型是有要求的。如果运算符发现,运算子的类型与预期不符,就会自动转换类型。比如,减法运算符预期左右两侧的运算子应该是数值,如果不是,就会自动将它们转为数值。'4' - '3' // 1
二、抽象值操作
2.1 ToString
抽象操作ToString负责处理非字符串到字符串的强制类型转换。
基本类型值的字符串化规则为:null转换为"null",undefined转换为"undefined",true转换为""true"。数字的字符串化遵循通用规则,那些极小和极大的数字使用指数形式:
对普通对象来说,除非自行定义,否则toString()返回内部属性[[Class]]的值,如"[object Object]"。
数组的默认toString()方法经过了重新定义,将所有单元字符串化以后再用","连接起来:
var a = [1,2,3]
a.toString() //"1,2,3"
2.2 ToNumber
抽象操作ToNumber将非数字值转换为数字值。
其中true转换为1,false转换为0,undefined转换为NaN,null转换为0。
ToNumber对字符串的处理基本遵循数字常量的相关规则(字符串中含有非数字类型字符返回NaN)。
对象(包括数组)会首先被转换为相应的基本类型值,如果返回的是非数字的基本类型值,则再遵循以上规则将其强制转换为数字。
2.3 ToPrimitive
抽象方法ToPrimitive将对象值转换为相应的基本类型值。该方法会首先检查该值是否有valueOf()方法,如果有并且返回基本类型值,就使用该值进行强制类型转换;如果没有就使用toString()的返回值(如果存在)来进行强制类型转换;如果valueOf()和toString()均不返回基本类型值,会产生TypeError错误。
从ES5开始,使用Object.create(null)创建的对象原型属性为null,并且没有valueOf()和toString()方法,因此无法进行强制类型转换。
2.4 ToBoolean
抽象操作ToBoolean将非布尔值转换为布尔值。
假值
以下这些值是假值
- undefind
- null
- false
- +0 ,-0,和NaN
- ""
从逻辑上说,假值列表意外的都是真值,但是JavaScript规范对此没有明确定义,只是给出了一些实例,例如规定所有的对象都是真值。
假值对象
var a = new Boolean(false)
var b = new Boolean(0)
var c = new Boolean("")
var d = Boolean(a && b && c) //true
a,b,c都是封装了假值的对象,但是d为true,说明a、b、c都为true。因此假值对象并非封装了假值的对象。
假值对象看起来和普通对象并无二致,但将它们强制类型转换为布尔值时结果为false。最常见的例子是document.all,它是一个类数组对象,包含了页面上所有元素,它以前曾是一个真正意义上的对象,布尔强制类型转换结果为true,不过现在它是一个假值对象。
真值
真值就是假值列表之外的值
三、显式强制转换
强制转换主要指使用Number()、String()和Boolean()三个函数,手动将各种类型的值,分别转换成数字、字符串或者布尔值。
显式转换为数字
Number(), parseInt(), parseFloat()
Number()
使用Number函数,可以将任意类型的值转化成数值
原始类型值
// 数值:转换后还是原来的值
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
对象
简单的规则是,Number方法的参数是对象时,将返回NaN,除非是包含单个数值的数组
Number({a: 1}) // NaN
Number([1, 2, 3]) // NaN
Number([5]) // 5
1,调用对象自身的valueOf方法。如果返回原始类型的值,则直接对该值使用Number函数,不再进行后续步骤。
2,如果valueOf方法返回的还是对象,则改为调用对象自身的toString方法。如果toString方法返回原始类型的值,则对该值使用Number函数,不再进行后续步骤。
3,如果toString方法返回的是对象,就报错。
var obj = {x: 1};
Number(obj) // NaN
// 等同于
if (typeof obj.valueOf() === 'object') {
Number(obj.toString());
} else {
Number(obj.valueOf());
}
Number函数将字符串转为数值,要比parseInt函数严格很多。基本上,只要有一个字符无法转成数值,整个字符串就会被转为NaN
parseInt
parseInt()针对的是将字符串解析为数字,非字符串参数会首先被强制转化为字符串.
解析字符串中的浮点数可以使用parseFloat()
var a = '42px'
parseInt(a) // 42
显式转换为字符串
String函数可以将任意类型的值转化成字符串,转换规则如下
原始类型值
数值:转为相应的字符串。
字符串:转换后还是原来的值。
布尔值:true转为字符串"true",false转为字符串"false"。
undefined:转为字符串"undefined"。
null:转为字符串"null"。
String(123) // "123"
String('abc') // "abc"
String(true) // "true"
String(undefined) // "undefined"
String(null) // "null"
对象
String方法背后的转换规则,与Number方法基本相同,只是互换了valueOf方法和toString方法的执行顺序。
String({a: 1}) // "[object Object]"
String([1, 2, 3]) // "1,2,3"
1,先调用对象自身的toString方法。如果返回原始类型的值,则对该值使用String函数,不再进行以下步骤。
2,如果toString方法返回的是对象,再调用原对象的valueOf方法。如果valueOf方法返回原始类型的值,则对该值使用String函数,不再进行以下步骤。
3,如果valueOf方法返回的是对象,就报错。
String({a: 1})
// "[object Object]"
// 等同于
String({a: 1}.toString())
// "[object Object]"
显式转为布尔值
一元运算符
一元运算符!
可以显式的将值强制转换为布尔值,同时还将真值反转为假值(或将假值反转为真值)所以显式强制类型转换为布尔值最常用的方法是!!
,以为第二个!
会将结果反转回原值
var a = '0'
!!a // true
var b = ''
!!b // fasle
Boolean()
Boolean()函数可以将任意类型的值转为布尔值。
它的转换规则相对简单:除了以下五个值的转换结果为false,其他的值全部为true。
1、undefined
2、null
3、0(包含-0和+0)
4、NaN
5、''(空字符串)
Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean(NaN) // false
Boolean('') // false
所有对象(包括空对象)的转换结果都是true,甚至连false对应的布尔对象new Boolean(false)也是true
Boolean({}) // true
Boolean([]) // true
Boolean(new Boolean(false)) // true
四、隐式强制类型转换
隐式类型转换是指那些隐蔽的强制类型转换。
隐式转换为布尔值
if(), for(..;..;..;), while(...), ? : 三元运算,|| ,&& (作为条件判断表达式)
JavaScript 遇到以上预期为布尔值的地方(比如if语句的条件部分),就会将非布尔值的参数自动转换为布尔值。系统内部会自动调用Boolean函数
1、undefined
2、null
3、+0或-0
4、NaN
5、''(空字符串)
if ( !undefined
&& !null
&& !0
&& !NaN
&& !''
) {
console.log('true');
} // true
隐式转换为字符串
+
运算符既能用于数字转化,也能用于字符串拼接。如果+
的其中一个操作数是字符串,则执行字符串拼接,否则执行数字加法。
'5' + 1 // '51'
'5' + true // "5true"
'5' + false // "5false"
'5' + {} // "5[object Object]"
'5' + [] // "5"
'5' + function (){} // "5function (){}"
'5' + undefined // "5undefined"
'5' + null // "5null"
隐式转换为数值
除了加法运算符(+)有可能把运算子转为字符串,其他运算符都会把运算子自动转成数值。
-
是数字减法运算符,因为 a-0 会将 a 强制类型转为数字。
a*1
和a/1
也可以将a转换为数字,不过不常见。
'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
五、总结
JavaScript的类型转换可以分为显式类型换和隐式类型转换
强制类型转换:Number() ,parseInt(), parseFloat(),String(),Boolean()、!
、!!
等
隐式类型转换
+
、 -
、 *
、 -
、 if()、 for(..;..;..;)、 while(...)、 ? : 三元运算、||(作为条件判断表达式) 、&& (作为条件判断表达式)
本文参考:
1、JavaScript 教程
2、《你不知道的JavaScript(中)》