JavaScript可以自由的进行数据类型转换,也提供了多种显式转换的方式。但是更多的情况下,是由JavaScript自动转换的,当然这些转换遵循着一定的规则,了解数据类型自由转换的规则是非常必要的。再次翻阅犀牛书后有了一些总结,与大家分享,有不严谨地方,望指正!

数据类型

  聊到数据类型转换,就不得不提到JavaScript的数据类型:原始类型(Number , String , Boolean , undefined ,  null ,  Symbol),对象类型 (Object)。当然Object有可以细分出 Array , Date , RegExp等对象。

  既然分为这么多种数据类型,每种数据类型肯定会有特定的用途,那么当提供的值的数据类型与预期不符时要怎么办呢,比如我需要在控制语句中使用到 boolean 值,提供的值却是 string 。当然我们可以显式转换 Boolean( a : string) ,但是根据日常经验,我们知道其实不需要这么复杂,可以在控制语句中直接用这个string类型的变量 ,也可以达到预期的效果。如下:

可见自动转换方便很多,但是在这个过程中到底是按照什么规则处理的呢?

自动转换

  什么时候会发生自动转换呢 ?

    犀牛书上是这样描述的: 当JavaScript期望使用一个布尔值的时候,你可以提供任意类型值,JavaScript将根据需要自行转换类型。一些值(真值)转换为true , 一些值(假值)转换为false 。这在其他类型中同样适用:如果JavaScript期望使用一个字符串,它把给定的值转换为字符串。如果JavaScript期望一个数字,它把给定的值转换为数字(如果转换结果毫无意义的话,将会返回NaN)。

    简而言之就是:JavaScript有一些语句/运算符对数据类型有要求,但我们提供的与预期不符时,就会发生自动类型转换。

  对数据类型有期待的语句和表达式:

    1、期待boolean类型的 : if 语句 、 do while 语句 、 while do 语句 、 &&  ||   ! (与或非逻辑表达式)  、 ? : ( 三目运算符)

    2、期待number类型的 :  + - * / % (算数运算符) 、  ++  --  (增量/减量运算符) 、 > 、  >= 、 <  、 <= 数字比较

    3、期待字符串的: + (字符串连接) 、 > 、  >= 、 <  、 <=  字母排序比较

    4、特殊的 : ==  、 !=  (不)相等运算符,在检测两个操作数是否相等时,会进行类型转换;(注意 :  === 、!==  是(不)严格相等运算符,是不会进行类型转换的)

  需要说明的是,1中当然可以传入表达式,但是表达式返回的结果也肯定会返回boolean类型的值,或者返回值被转换为boolean;2和3有一些重复的运算符 : + 、 > 、  >= 、 <  、 <= ,这些运算符在不同场景下发生自动转换的时候,会有不同的优先级。有如下场景:

// + 的场景   +有两种作用:算数运算和字符串连接。所以期待的是数字和字符串!
// 1、两个操作数同为数字,或者同为字符串,不需要进行转换
1 + 1 // 2
'1' + '1' // '11'
// 2、有一个操作数是字符串,则另外一个也会转换为字符串
'1' + 1 // "11"
'1' + null // "1null"
'1' + {} // "1[object Object]"
'1' + new Date() // "1Wed Jun 20 2018 11:49:55 GMT+0800 (中国标准时间)"
// 3、如果有一个操作数是对象的话,会转化为原始值(除了Date对象是调用toString()方式转换 , 其他对象都会调用 valueOf() 进行转换 , 但是由于多数对象只是简单的继承了valueOf() , 只会返回对象,而不是一个原始值,所以会再调用toString进行转换) , 所以这里可以简单的理解为:都会转换为字符串 。 另一个操作数也会转换为字符串
1 + {} // "1[object Object]"
1 + new Date() // "1Wed Jun 20 2018 11:56:56 GMT+0800 (中国标准时间)"
1 + [] // "1"
// 4、 其他情况都会转换为数字
1 + null //
1 + undefined // NaN

  从例子中可以看到,+ 的转换其实是优先转换为字符串的,如果操作数中又字符串或者对象(对象在这里会转换为字符串),则会按照 字符串连接进行操作的。从例子的第3个可以看到,第一个操作数都是数字,但是会转化为字符串。例子中的第4个,没有对象和字符串,null 和 undefined 都转换为 数字进行算数运算,其中undefined -> number 会返回 NaN , 所以计算结果为NaN。

  “+”还有特殊的用法,就是转换为数字,如下。会将+后的操作数转换为数字,具体的转换规则后续会说明。

+ null   //
+ undefined // NaN
+ {} // NaN
+ new Date() //
+ ["5"] //
+ "4" //

   > 、  >= 、 <  、 <=  这些比较运算符的规则和 + 类似,不过是会优先转换为数字进行比较。

// 作用 : 比较数值大小或者再字母表中的位置。也是期待数字和字符串!
1、两个操作数中只要有一个不是字符串,则两个值都转为数字
"3" > "11" // true 字符串比较
3 > "11" // false 11 转换为数字
 true > '0' // true true 和 ‘0’ 都转换为数字
2、对象同样会转换为原始值(不过这里的Date对象也是优先调用valueOf ,返回的是毫秒数,其他的和上述 + 的一样),如果转换后有一个字不是字符串,则两个值也都需要转换为数字
1000 > new Date() // false
100000000000000000000000 > new Date() // true date对象转换为数字
"100000000000000000000000" > new Date() // true 左值也随着 date对象一起转换为数字
'11' > ["3"] // false 数组转为字符串,所以这里是字符串比较

  这里需要注意的是,只要在转换为数字的过程中,有一个值是NaN,那么比较的结果肯定是false。

  == 、 !=  (不)相等运算符是不严格的比较,所以,如果两个操作数不是同一类型,那么会尝试进行一些类型转换,然后进行比较。有以下规则和类型转换:

  1、一个值是undefined,一个值是null,则相等

  2、一个值是数字,一个值是字符串,则字符串转换为数字进行比较

  3、true 和 false 会分别转换为 1 和 0

  4、一个值是字符串或者数字,另一个是对象,对象转换为原始值(Date类只调用toString,其他的和之前的一致),然后进行比较。

  5、其他的比较,全是false。

null == undefined  // true  1
null == 0 // false 5
1 == '1' // true 2
1 == true // true 3
2 == true // false 3
1 == [1] // true 4
'1' == ['1'] // true 4 数组转为字符串
1 == ['1'] // true 4 数组转为字符串再转为数字

  

  还有一种自动转换也很容易被忽略,但是经常见到。那就是对象包装

  思考一个问题,为什么数字是原始类型,却可以使用toString方法? 只有对象才会有方法的,为什么数字却可以使用。

let x = 1
x.toString() // "1"

  因为在x需要使用方法的时候,JavaScript会通过调用 new Number(x) 的方式将它暂时转换为对象,它继承了Number对象的方法,所以就可以调用toString了。同样的还有字符串、布尔值,也是通过各种的构造函数进行转换。这也是为什么undefined和null,不可以使用toString的原因,因为它们没有构造函数。

x = null
x.toString()
//VM289:1 Uncaught TypeError: Cannot read property 'toString' of //null
// at <anonymous>:1:3
//(anonymous) @ VM289:1 x = undefined
x.toString() //VM305:1 Uncaught TypeError: Cannot read property 'toString' of //undefined
// at <anonymous>:1:3

  目前我所了解的自动转换就只有这么多,后续再继续补充。那么自动转换的过程中,又有哪些规则呢?

any -> boolean

  在其他类型的值转换为boolean是,只有这几个会转换为false,其他都是true : undefined 、 null 、 "" 、 0 、-0 、NaN。

Boolean(0)  //  false
Boolean("") //false
Boolean(NaN) //false
Boolean(undefined) //false
Boolean(null) // false // 空对象 空数组 空函数 都会true
Boolean({}) // true
Boolean([]) //true
Boolean(function () {}) // true // 此时是一个boolean对象,而不是原始值,所以是true
Boolean(new Boolean(false)) // true

any -> number

  在其他类型的值转换为number是,就复杂一些:

  1、boolean -> number

    true ->  1

    false -> 0

  2、string -> number

    由数字组成的字符串,可以直接转换为数字,开始和结尾的空格都可以忽略。不符合的字符串会返回NaN。

+''   //  0  空字符串
+'100' //
+' 100 ' // 100 忽略前后空格
+' 100aa' // NaN 有其他非数字

    备注:这里的规则是自动转换的规则,如果是显示转换的话,构造函数Number() 和此规则一致,而window.parseInt()  window.parseFloat的解析规则则不一样。如下

window.parseInt('  100a  ')   //  100
window.parseFloat(' 100.11a') // 100.11

  3、对象 -> number

    对象会先尝试调用 valueOf 返回原始值,如果没有则调用toString返回原始值,再进行转换返回。看几个例子

+new Date()  //  1529483712712  date对象的valueOf返回毫米数,即为数字
+[] // 0 数组valueOf为它自己,再调用toString 返回 “” ,空字符串转换为数字为0
+['1'] // 1 同样toString 返回 “1” , 转换为数字为 1
+['1','2'] // NaN toString 返回 “1,2” 转换为数字 NaN
+{} // NaN toString [Object,Object] , 转换为数字 NaN

  4 、 undefined  null

    null -> 0

    undefined -> NaN

any -> string

  1、null undefined boolean  number

    这几个原始类型的转换非常简单,就是将自身用引号包裹而已。

'' + 1  //  "1"
'' + true // "true"
'' + undefined // "undefined"
'' + null // "null"

  2、对象 -> string

    和对象转化为数字类似,不过是先调用toString,在调用valueOf。

'' + {}  //   "[object Object]"
'' + [] // ""
'' + [1,2,3] // "1,2,3"
'' + function() {} // "function () {}"
'' + new Date() // "Wed Jun 20 2018 16:50:56 GMT+0800 (中国标准时间)"

    可以看出不同的对象差别挺大的,数组会将每个元素用逗号分开,生成字符串,date对象toString返回的是中国标准时间,从这里就可以看过和转化成数字的不同逻辑了,先尝试toString  不行才再valueOf。

总结

  自动类型转换真的非常常见,常用的一些便捷的转类型的方式,都是依靠自动转换产生的。比如 转数字 : + x    、  x - 0  ,   转字符串 :   "" + x  等等。现在总算知道为什么可以这样便捷转换。

  总结的大多来自于犀牛书,多翻翻犀牛书,没毛病。

JavaScript 那些不经意间发生的数据类型自动转换的更多相关文章

  1. JAVA数据类型自动转换,与强制转换

    一.数据类型自动转换 public class Test{ public static void main(String[] args){ int a = 1; double b = 1.5; dou ...

  2. php之数据类型自动转换

    1:概述 ---php是一种弱类型的语言,它可以根据运行环境的变化而自动进行数据类型的转换 1.1转换成布尔类型的原则 以下值都将转换成布尔类型中的false: A.布尔类型的false; B.空字符 ...

  3. struts2中的数据类型自动转换

    参考:https://blog.csdn.net/qq_35326718/article/details/72453042 https://www.cnblogs.com/aigeileshei/p/ ...

  4. Java数据类型自动转换(++ ,+=)

    在算术表达式中的自动类型转换 数据从类型范围小的自动向数据范围大的转换 整数向浮点数转换(包括long类型向float转换) 例子: char类型的范围内与整数之间转换依据ASCII表 强制转换会丢失 ...

  5. php中数据类型自动转换

    1.1 转为布尔型(即返回值为0) 空字符串''或"" 数字0或0.0 字符'0'或"0" 空值NULL 没有成员的数组    其余都转换成布尔型true,包含 ...

  6. java的数据类型的转换

    一:java的数据类型转换除布尔类型boolean(不能转换)有两种:<一> 自动转换: <二> 强制转换 <一>.自动转换:就是将小的数据类型自动转换成大的数据类 ...

  7. struts2(三)之表单参数自动封装与参数类型自动转换

    前言 对struts2的使用不外乎这几点,参数自动封装,拦截器的使用,数据校验,ognl表达(值栈和actionContext的讲解),struts2的标签,struts2的国际化, struts2的 ...

  8. tp类型自动转换和自动完成

    一.类型自动转换 在模型中对数据库字段自动完成 //模型中数据类型自动转换 添加一个$type数组即可protected $type=array( 'username'=>'serialize' ...

  9. 建议2:注意Javascript数据类型的特殊性---(2)慎用JavaScript类型自动转换

    在JavaScript中能够自动转换变量的数据类型,这种转换是一种隐性行为.在自动转换数据类型时,JavaScript一般遵循:如果某个类型的值被用于需要其它类型的值的环境中,JavaScript就自 ...

随机推荐

  1. 24、JSON与OC互相转化

    一. JSON: 1. 01.JSON是一种轻量级的数据格式,一般用于数据交互 02.服务器返回给客户端的数据,一般都是JSON格式活着XML格式(文件下载除外) JSON的格式很像OC中的字典和数组 ...

  2. mount 移动硬盘出现的各种小问题

    1.fdisk -l 查看硬盘是否存在 2.新建要挂载硬盘的文件夹 mkdir  /disk   (如果想要挂载到已存在的目录就不要新建了) 3.挂载硬盘:mount /dev/sdc /disk 4 ...

  3. Oracle 导出错误 EXP-00000~EXP-00107

    EXP-00000: Export terminated unsuccessfully Cause: Export encountered an Oracle error. Action: Look ...

  4. Oracle中根据当前时间和活动类型去数据库查询活动id

    活动类型默认是1,代表邀请好友 select * from t_invite_activityinfo twhere sysdate >= t.begintime and sysdate< ...

  5. fPLL结构及动态配置

    输入参考时钟 从上图可以看到参考时钟输入的几种类型.   注意:fPLL的校正是由CLKUSR来驱动的,这个时钟必须要保持稳定. 参考时钟利用器     N计数器 N计数器会把参考时钟利用器输出进行分 ...

  6. WordPaster-KesionCMS V9整合教程

    注意:KesionCMS V9使用的是JQuery 1.10.3版本.需要到JQuery UI官网下载JQuery 1.10.3的UI库. JQueryUI官网:http://jqueryui.com ...

  7. 11-DOM介绍

    什么是DOM DOM:文档对象模型.DOM 为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构.目的其实就是为了能让js操作html元素而制定的一个规范. DOM就是由节点组成的. 解析过程 ...

  8. Android自定义视图四:定制onMeasure强制显示为方形

    这个系列是老外写的,干货!翻译出来一起学习.如有不妥,不吝赐教! Android自定义视图一:扩展现有的视图,添加新的XML属性 Android自定义视图二:如何绘制内容 Android自定义视图三: ...

  9. How to transfer developer profile to one mac to another mac

    Export developer profile from old mac. In the Xcode Organizer, select your team in the Teams section ...

  10. java基础-day13

    第01天 java面向对象 今日内容介绍 u 继承 u 抽象类 第1章   继承 1.1  继承的概述 在现实生活中,继承一般指的是子女继承父辈的财产.在程序中,继承描述的是事物之间的所属关系,通过继 ...