JavaScript 是一种动态类型语言,变量没有类型限制,可以随时赋予任意值。
var x = y ? 1 : 'a';
上面代码中,变量x
到底是数值还是字符串,取决于另一个变量y
的值。y
为true
时,x
是一个数值;y
为false
时,x
是一个字符串。这意味着,x
的类型没法在编译阶段就知道,必须等到运行时才能知道。
虽然变量的数据类型是不确定的,但是各种运算符对数据类型是有要求的。如果运算符发现,运算子的类型与预期不符,就会自动转换类型。比如,减法运算符预期左右两侧的运算子应该是数值,如果不是,就会自动将它们转为数值。
'4' - '3' // 1
上面代码中,虽然是两个字符串相减,但是依然会得到结果数值1
,原因就在于 JavaScript 将运算子自动转为了数值。
上次我们学习了js的数据类型,有数值(number),字符串(string),布尔值(boolean),null,undefined,symbol,对象(object),以及新增的BigInt。
1.任意类型转换成string的方法
- String(x)
String(123)>'123'//数值转换成字符串
String(true)>'true',String(false)>'false'//布尔值转换成字符串
String(null)>'null'//null转成字符串
String(undefined)>'undefined'//undefined转换成字符串
String({name:'xue',age:15})>'[object,Object]'//对象(狭义的对象)返回一个类型字符串
String([])>''//如果是数组,返回该数组的字符串形式,空数组返回空字符串
String (function(){})>'function(){}'//函数则返回函数本身的字符串形式。
- n.toString()
除了null和undefined以外的任何值都具有toString()方法。
![4b38c990b5b6d877d7bb138f10fb405e.png](https://i-blog.csdnimg.cn/blog_migrate/0257b71ac4116d54cfe3e5664e40f461.jpeg)
上面函数和空对象之所以加(),是因为浏览器会把他们默认为语句,所以转换时会报错,加上()浏览器就会默认为对象,再进行转换,下面的的方法也是如此。
- x+''
JavaScript中的某些运算符会做隐式的类型装换,很多老司机们就习惯于用运算符来进行类型转换,比如‘+’,两个操作数,一个是字符串的话,就会把另一个操作数转换成字符串。
x+ '' //等同于String(x)
![128244d3acd2104a081047e1343ee252.png](https://i-blog.csdnimg.cn/blog_migrate/ec372bf2552e8fc69df2799bfe2fbaf9.jpeg)
上图中,加了圆括号的正常识别,没有加圆括号就被浏览器解读成了语句,被忽略,所以上述代码就变成了
+‘’+x等同于number(x),转换成数值了。‘’转换成数值就是0.
2.任意类型转换成number
- number()
![c86e9dc54a0e4477d30f044f3811f590.png](https://i-blog.csdnimg.cn/blog_migrate/ad4293e8de04f7686570e25f9aa5c901.jpeg)
![1863437ba5841dbd4f3204b8c7a8a80c.png](https://i-blog.csdnimg.cn/blog_migrate/122942489b7d5a82f4e50ad3abc33e83.jpeg)
函数将字符串转为数值,要比parseInt
函数严格很多。基本上,只要有一个字符无法转成数值,整个字符串就会被转为NaN
。
parseInt('42 cats') // 42
Number('42 cats') // NaN
上面代码中,parseInt
逐个解析字符,而Number
函数整体转换字符串的类型。
另外,parseInt
和Number
函数都会自动过滤一个字符串前导和后缀的空格。
parseInt('tvr12.34n') // 12
Number('tvr12.34n') // 12.34
简单的规则是,Number
方法的参数是对象时,将返回NaN
,除非是包含单个数值的数组。
Number({a: 1}) // NaN
Number([1, 2, 3]) // NaN
Number([5]) // 5
之所以会这样,是因为Number
背后的转换规则比较复杂。
第一步,调用对象自身的valueOf
方法。如果返回原始类型的值,则直接对该值使用Number
函数,不再进行后续步骤。
第二步,如果valueOf
方法返回的还是对象,则改为调用对象自身的toString
方法。如果toString
方法返回原始类型的值,则对该值使用Number
函数,不再进行后续步骤。
第三步,如果toString
方法返回的是对象,就报错。
请看下面的例子。
var obj = {x: 1};
Number(obj) // NaN
// 等同于
if (typeof obj.valueOf() === 'object') {
Number(obj.toString());
} else {
Number(obj.valueOf());
}
上面代码中,Number
函数将obj
对象转为数值。背后发生了一连串的操作,首先调用obj.valueOf
方法, 结果返回对象本身;于是,继续调用obj.toString
方法,这时返回字符串[object Object]
,对这个字符串使用Number
函数,得到NaN
。
默认情况下,对象的valueOf
方法返回对象本身,所以一般总是会调用toString
方法,而toString
方法返回对象的类型字符串(比如[object Object]
)。所以,会有下面的结果。
Number({}) // NaN
如果toString
方法返回的不是原始类型的值,结果就会报错。
var obj = {
valueOf: function () {
return {};
},
toString: function () {
return {};
}
};
Number(obj)
// TypeError: Cannot convert object to primitive value
上面代码的valueOf
和toString
方法,返回的都是对象,所以转成数值时会报错。
从上例还可以看到,valueOf
和toString
方法,都是可以自定义的。
Number({
valueOf: function () {
return 2;
}
})
// 2
Number({
toString: function () {
return 3;
}
})
// 3
Number({
valueOf: function () {
return 2;
},
toString: function () {
return 3;
}
})
// 2
上面代码对三个对象使用Number
函数。第一个对象返回valueOf
方法的值,第二个对象返回toString
方法的值,第三个对象表示valueOf
方法先于toString
方法执行。
- + x
+ x // 等同于number(x) - x-0
x-0 // 等同于number(x) - parseInt()
parseInt()函数是全局函数,不属于任何类的方法,用于解析整数。
如果字符串前缀是“0x”或“0X”,parseInt()就将其解释为十六进制数。
parseInt()会跳过任意数量的前导空格,尽可能解析更多的数值字符,忽略后面不能转换的。
若开头第一个字母就不能转换,即第一个非空格字符是非法的数字直接量,就返回NaN。
parseInt()可以接受第二个参数,用来指定数字转换的基数(2进制,8进制,16进制等),即(2~36之间,不在区间内,返回NaN)表示被解析值的进制,返回对应10进制。
- parseFloat()
parseFloat()函数是全局函数,不属于任何类的方法,用于解析浮点数。
parseFloat()会跳过任意数量的前导空格,尽可能解析更多的数值字符,忽略后面不能转换的。
若开头第一个字母就不能转换,即第一个非空格字符是非法的数字直接量,就返回NaN。
3.任意类型转换成Boolean
一共两种方法,一是Boolean(x),一是!!x
注意,undefined,null,0,NaN,'',五种转换为布尔值时是flase,其余均为true,
[]和{}也为true.
关于转化为对象的问题后面再写