一.定义
隐式转换是指在JavaScript中,当运算符在运算时,如果两边数据不统一,CPU就无法计算,这时我们编译器会自动将运算符两边的数据做一个数据类型转换,转成一样的数据类型再计算。这种无需程序员手动转换,而由编译器自动转换的方式就称为隐式转换。
二.转换规则
JavaScript的类型分为基本数据类型和引用数据类型:
基本数据类型: Undefined、 Null、 String、 Number、 Boolean、(Symbol)->ES6
引用类型:Object
其直接转换规则如下表:
而当使用运算符时,两边不同的数据类型的自动转换有一套自己的默认规则,在JavaScript权威指南中这么说明:
以上面的解释,归类为以下规则:
转为String类型:
字符串连接符:+
例:String(1) + "10" = "1" + "10" = "110"
注:只要加号两边有一边是字符串,则为字符串运算符。
转为Number类型:
自增自减运算符:++ / --
算术运算符:+ - * / %
关系运算符: > < >= <= == != === !==
转为Boolean类型:
逻辑非运算符: !
转为布尔类型成为false的有:
undefined、null、空字符串、0、-0、NaN
new Number() 和 Number() 是不同的,new Number() 创建了一个Number对象,Number() 将传入的参数转换为数值字面量
再举一些例子:
1 + "true" // "1true" 若+两边存在一个字符串,将另一个也转为字符串进行字符串拼接 String(1) + "true" = "1true"
1 + true // 2 这里的 + 是算术运算符 1 + Number(true) = 1 + 1 = 2
1 + undefined // NaN 这里的 + 是算术运算符 1 + Number(undefined) = 1 + NaN = NaN
1 + null // 1 这里的 + 是算术运算符 1 + Number(null) = 1 + 0 = 1
1 + "10" // "110" 这里的 + 是字符串连接符 String(1) + "10" = "1" + "10" = "110"
1 - "10" // -9 这里的 + 是算术运算符 1 - Number("10") = 1 - 9 = -9
//不要混淆字符串连接符与算术运算符隐式转换规则
"2" > 10 // false Number(2) > 10 = 2 > 10 = false
"2" > "10" // true 当两边都是字符串的时候,此时转为number然后比较关系,注意这里并不是按照Number()的形式转为数字,而是按照字符串对应的unicode编码来转成数字,charCodeAt(index) index为字符下标,默认为0。
"2".charCodeAt(0) > '10'.charCodeAt(0) = 50 > 49 = true
"abc" > "b" // false 多个字符的时候从左往右依次比较 'a'.charCodeAt(0) = 97 'b'.charCodeAt(0) = 98
"abc" > "aad" // true
NaN == NaN // false
特殊情况:如果数据类型是undefined或null 得出固定结果
undefined == undefined // true
undefined == null // true
null == null // true
NaN == NaN // false
三、对象的类型转换
//对象转为布尔值一直为true
//对象
var a = { b: 1 }
a.toString() ⇒ "[object Object]"
a.valueOf() ⇒ {b: 1}
//数组
var a = [1,2,3]
a.toString() ⇒ "1,2,3"
a.valueOf() ⇒ [1, 2, 3]
//函数
var a = function () { b =333; return 111; }
a.toString() ⇒ "function(){b =333; return 111;}"
a.valueOf() ⇒ ƒ () { b =333; return 111; }
//日期
var a = new Date()
a.toString() ⇒ "Thu Mar 07 2019 13:48:31 GMT+0800 (中国标准时间)"
a.valueOf() ⇒ 1551937711874
//错误
Error
toString()返回:"Error {错误描述}"
valueOf()返回:错误本身
//正则表达式
var a = new RegExp('^ass[^f]\w?','gi')
a.toString() ⇒ "/^ass[^f]\w?/gi"
a.valueOf() ⇒ "/^ass[^f]\w?/gi"
四、总结和实践
1、 算术运算符(+、-、*、/、++、–、%…)
'+'
作为一个双目运算符: 若+两边存在一个字符串
,将另一个也转为字符串进行字符串拼接。
其他情况下,不管双目还是单目,都转为数值类型
2、关系运算符(>、<、==、!=…)
===
、!==
:同时对比类型和值,两个都为真才返回真==
、!=
: 若两边均为对象,对比它们的引用是否相同!(逻辑非)
: 将其后变量或表达式转为布尔值对比字符串
:从头至尾扫描逐个比较每个字符的unicode
码,直到分出大小其他情况下,两边均转为数值类型
NaN与任何值都不相同,与任何值比较都返回false
对象类型在运算时进行类型转换都先调用valueOf()方法,再尝试toString()方法
在进行对象字面量(这里说的是JSON格式的对象字面量)运算时要注意,若运算符两边都是字面量,
则将它们都视为对象字面量进行类型转换;
若只有一个字面量时要注意,当这个字面量在首位时,会被当做一个块看待。
{} + {} => "[object Object][object Object]"
{}被当做一个块,相当于执行 ( {}, +[] ),计算的是+[]的结果
{} + [] => 相当于{}; + [],即前面为代码执行掉了,仅剩 +[] => +"" => 0
{ a: 1 } + [] => 0
{} == [] => 报错 ({}, ==[]) => 报错
变量形式运算正常
var a = { q:1 }
a + [] => "[object Object]"
[] + a => "[object Object]"
[1,2,3] + [] => "1,2,3" + "" => "1,2,3"
[] + {} => "" + "[object Object]" => "[object Object]"
[] == 0 // true [] => "" => 0
![] == 0 // true ![] => false => 0
[] == ![] // true [] => "" => 0 ![] => false => 0
[] == [] // false 比较引用地址
{} == {} // false 比较引用地址
{} == !{} // false !{} => false => 0 {} => "[object Object]" => Number("[object Object]") => NaN
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。