先来看一个栗子:
if('0.00'){
console.log('0.00')
}
var obj = {
valueOf: function(){ return {} },
toString: function(){ return {} }
}
console.log(obj == 0)
知道上面的栗子输出上面吗?
首先,JavaScript的内置类型有:null
,undefined
,number
,string
,boolean
,object
,symbol
(ES6)。除去object
,其他算是基本类型(primitives)。把一个值从一个类型转换成其他的类型的做法叫做类型转换。可以是显示的,也可以是隐式的。
抽象值操作
类型的转换涉及到了转换的基本规则,这里介绍ToString
,ToNumber
,ToBoolean
,ToPrimitive
。
ToString
参数 | 结果 |
---|---|
undefined | "undefined" |
null | "null" |
Boolean | "false" or "true" |
Number | 将数字转化成字符串,如"1.1" |
String | 不变 |
Object | ToPrimitive 后ToString |
ToNumber
参数 | 结果 |
---|---|
undefined | NaN |
null | +0 |
Boolean | false->0, true->1 |
Number | 不变 |
String | 转换规则间下面* |
Object | ToPrimitive 后ToNumber |
String 的
ToNumber
规则。字符串和数字的字面量差不多(其他情况转化为NaN),即:
允许字符串前后有空白符
允许前面是0而不会被转化为8进制
允许用+/-代表符号位
只有空白符的情况下,转化为0
ToBoolean
参数 | 结果 |
---|---|
undefined | false |
null | false |
Boolean | 不变 |
Number | 0,NaN->false; other->true |
String | length等于0->false; other->true |
Object | true |
ToPrimitive
参数 | 结果 |
---|---|
undefined | 不变 |
null | 不变 |
Boolean | 不变 |
Number | 不变 |
String | 不变 |
Object | 转化规则见下面* |
这里涉及到了
ToPrimitive ( input [, PreferredType] )
,input
为输入的值,PreferredType
为可选项(默认情况下是Number
。另一个是String
,作用和Number
相反,先执行toString()
,在执行valueOf()
)。
默认情况下(PreferredType为Number
),内部先执行valueOf()
得到的值如为primitive
(基本类型)则输出结果,否则再执行toString()
得到的值如为primitive
则输出结果,否则报错。
两种转换
理解了上面的抽象值操作,就可以来看一下下面两种不同的转换。
显式转换
String():满足ToString
转换规则
String(null) //"null"
Number():满足ToNumber
转换规则
Number(' 010 ') //10
Boolean:满足ToBoolean
转换规则
Boolean([1, 2, 3]) //true
parseInt(string, radix):满足ToString
转换规则
var a = {
//先执行toString
toString: function () {
return {}
},
//再执行valueOf
valueOf: function () {
return 0x10
}
}
parseInt(a) //16
需要注意的是,由于
a
是对象,需要通过ToPrimitive
得到Primitive
(此时ToPrimitive ( input [, PreferredType] )
的PreferredType
为String
),再将ToString(Primitive)
得到"0x10"
隐式转换
一元操作符+:满足ToNumber
转换规则
var a = "6";
+a + 6 //12
二元操作符 +:
分别计算左右操作数,得到lval,rval。(有步骤合并省略)
lprim = ToPrimitive(lval)。
rprim = ToPrimitive(rval)。
如果lprim或rprim是字符串,都转换为字符串然后相加返回。
都转换为数字相加后返回。
[1, 2] + 1 //"1,21"
二元操作符 -:
分别计算左右操作数,得到lval,rval。(有步骤合并省略)
lnum = ToNumber(lval)。
rnum = ToNumber(rval)。
相减后返回。
[1, 2] - 1 //NaN
条件 if(express)(||、&&、三元...):满足ToBoolean
转换规则
if (' ') {
console.log('blank')
}
//blank
==运算:
Type(x) | Type(y) | Result |
---|---|---|
两者类型相同 | 遵循===运算 | |
null | Undefined | true |
Undefined | null | true |
Number | String | x == toNumber(y) |
String | Number | toNumber(x) == y |
Boolean | (any) | toNumber(x) == y |
(any) | Boolean | x == toNumber(y) |
String or Number | Object | x == toPrimitive(y) |
Object | String or Number | toPrimitive(x) == y |
otherwise… | false |
var a = {
toString () {
console.log('toString');
return '1'
},
valueOf () {
console.log('valueOf');
return 1
}
}
console.log('1' == a) // true
===运算:
Type(x) | Values | Result |
---|---|---|
两者类型不一样 | false | |
Undefined or Null | true | |
Number | 两者数值一样(非NaN) | true |
String | 两者完全一样 | true |
Boolean | 两者一样 | true |
Object | 两者指向同一个对象 | true |
otherwise… | false |
关系比较(如<)
主要步骤:首先都转换为基础类型,如果都是字符串,按字符串比较;否则都转数字比较。
==运算
===运算