javascript类型转换
JavaScript中有七种类型,它们互相之间可以转换,但要搞清楚其中的转换关系可不简单。
JavaScript类型
类型种类
在JS中,有6种基本类型和一种引用类型,分别是:
基本类型:
- null
- undefined
- boolean
- number
- string
- symbol(ES6新增)
引用类型:
object
类型检测
一般来说,我们可以用typeof来检测某个值的数据类型,比如:
1 | typeof undefined === "undefined"; // true |
但是有一个例外: null,这也是一个bug
1 | typeof null === "object"; // true |
如果想检测某个值是否是null,则可以这样:
1 | var a = null; |
需要注意的是,function和array其实也是object,但它们有所区别:
1 | typeof function a(){ /* .. */ } === "function"; // true |
如果要检测a是否是数组,可以用instanceof
1 | var a = [123]; |
类型转换抽象操作
ToString
当一个非String类型的值要转换为String,我们可以用ToString
操作。
toString()
对于基本类型来说,它们有自然的转换关系。如:null变成”null”,undefined变成”undefined”,true变成”true”,number自然转换为数字字符串,但如果对于非常大的数,则会转换为指数形式。
对于object来说,toString()
(代表着Object.prototype.toString()
)将会返回[[class]]
原型,比如说”object Object”;但如果是数组,则重写了toString()
方法,会返回一个以逗号分隔数组值的字符串。比如:
1 | var a = [1,2,3]; |
JSON.stringify()
另一种转换为字符串的方法就是JSON.stringify,对大多数基本类型,它的转换方法和toString是一样的:
1
2
3
4
1 | JSON.stringify( 42 ); // "42" |
但不同的是,JSON.stringify会忽略掉undefined、function和symbol。请看下面的例子:
1 | JSON.stringify( undefined ); // undefined |
如果JSON.stringify调用了循环引用的object,则会抛出Error
。如果JSON.stringify调用的对象有toJSON()
方法,则会对toJSON()的返回值再进行stringify。
1 | var a = { |
ToNumber
转换为number,我们可以用ToNumber操作。
Number()
对于基本类型,转换规则为:true -> 1,false -> 0,undefined -> NaN,null -> 0,字符串如果包含字母则转换为NaN。
对于将某值转换为基本数据类型,通常会调用ToPrimitive操作,首先看该值有没有valueof()方法,如果没有则调用toString()方法,如果二者都没有,则抛出TypeError。
比如:
1 | var a = { |
ToBoolean
将一个值转换为Boolean值,我们先看一个false表:
1 | undefined |
任何不在这个表上的值都为true。
比如:
1 | var a = new Boolean( false ); |
显式转换
之前提到过一些显式转换,但其实还有以下几种:
字符串与数字的转换
1 | var a = 42; |
日期转换为数字
Date转换为的数字为从1 January 1970 00:00:00 UTC 到Date的毫秒数。
1 | var d = new Date( "Wed, 2 Aug 2017 08:53:06 CDT" ); |
Date.now()方法就是用的这种转换:
1 | if (!Date.now) { |
~操作符
Js里有”~“操作符,它首先将值转换为32bit的数字,然后在对它进行取补码,也就是说,”~x”相当于”-(x+1)”。
于是,~有一个用处就是判断-1,比如我们对字符串使用indexOf()时如果找不到则返回-1,我们可以这样写:
1 | var a = "Hello World"; |
除此之外,~~可以用来对小数进行取整,但要注意的是,它是舍弃小数位数,而不是四舍五入,相当于Math.ceil():
1 | Math.floor( -49.6 ); // -50 |
parseInt()方法
该方法可以将字符串转换为数字,而且可以接受第二个参数,表示要转换的进制。但要注意的是,它有几个特别的地方:
1 | parseInt( 0.000008 ); // 0 ("0" from "0.000008") |
所以,要谨慎使用parseInt。
转换为Boolean
我们已经知道Boolean()方法可以将值转换为Boolean,但还有一个更快的方法,就是使用!!操作符:
1 | var a = "0"; |
隐式转换
数字转换为字符串
因为字符串可以用+连接,所以当我们把数字和字符串用+连接时,数字会强制转换为字符串:
1 | var a = 122; |
字符串转换为数字
因为-只在数字运算符中才有定义,所以对字符串使用-会被强制转换为数字:
1 | var a = "122"; |
数组转换为数字
同样的,如果数组中只有一个值,使用-时,会先把数组转换为字符串,再转换为数字:
1 | var a = [3]; |
操作符的妙用
操作符||和&&
我们都知道||代表‘或’,&&代表‘和’,但是与Java、C++等语言不同的是,使用这两个操作符时,它们返回的不是true或false,而是本身的值,举个例子:
1 | var a = 42; |
于是我们就可以利用这两个操作符进行一些赋值操作:
1 | a || b; |
操作符==与===
这两个符号我们应该很熟悉了,==代表值的比较,如果二者类型不同,会进行强制转换;===则是二者值与类型都相同才为true。这里需要注意一些问题:
NaN不等于它本身
+0等于-0
字符串与数字比较
二者比较时,使用===结果肯定为false,因为二者类型不同,但如果使用==,则需要进行转换,简单来说就是把字符串转换为数字再对二者的值进行比较:
1 | var a = 22; |
任何值与Boolean比较
当任何值与Boolean使用==比较时,首先会把Boolean转换为数字,然后再进行比较。也就是说:
1 | var x = true; |
所以,在任何时候,都不要使用== true或者== false这样的语句。
null与undefined比较
当使用==比较null和undefined时,结果总为true。
Object与非Object比较
当object/function/array与String或者Number进行==比较时,会先把Object转换为String或Number,然后再对值进行比较,而Boolean值会被转换为Number再进行比较。
一些值得注意的比较
1 | "" == [null]; // true |
总结
需要特别注意的就是隐式转换,将对象转换为基本类型时,会先调用valueOf()
方法,没有才调用toString()
方法,如果我们给自定义的对象添加valueOf()
方法,并自己给返回值,也能能起到转换的效果。还有就是,在进行等于比较时,还是用===比较安全。
参考资料: You-Dont-Know-JS
本文标题:javascript类型转换
文章作者:flyrk
发布时间:2017-08-02
最后更新:2022-02-25
原始链接:https://flyrk.github.io/2017/08/02/js-value-coercions/
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 CN 许可协议。转载请注明出处!
分享