乐趣区

关于前端:JavaScript隐式转换问题

一. 定义

  隐式转换是指在 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
退出移动版