JS是弱类型语言,这意味着在JS中没有确定类型的变量,其类型只取决于当时的值的类型.当我们进行操作的时候,有时候需要用到一些类型变换.这其中就分为显示转换和隐士转换.JS的数据类型有8种,Number、String、Boolean、undefined、Object、Null、bigInt、Symbol,其中基础类型(原始值):Number、String、Boolean、undefined、Null、bigInt、Symbol,复杂类型(对象值):Object(Function、Array、Date、RegEx等)
显示转换
Number
- Number: 严格转换利用
Number强制转换为数字ToNumber - parseInt:从左到右依此转换,能转换就转换不能转换就停止;如果第一个就不能转换返回
NaN;转换为整数 - parseFloat:从左到右依此转换,能转换就转换不能转换就停止;如果第一个就不能转换返回
NaN;可以转换小数 - Math.round: 四舍五入,如果出现非数字字符,返回
NaN
String
- String: 严格转换,利用
String强制转换为字符串ToString - toString: JS提供的
toString方法转换字符串
Boolean
- Boolean: 严格转换,利用
Boolean强制转换为布尔值
隐士转换
隐士转换一般发生在使用操作符时,其中尤以+、==引起的问题居多,其他操作符一般都针对number类型(将运算的值转为number类型即可).JS隐士转换主要分为:ToPrimitive(转为原始值)、ToNumber(转为数字)、ToString(转为字符串).
ToPrimitive
JS引擎提供ToPrimitive(input,preferredType?)通过一个必传参数input和一个可选参数preferedType(Number或String)来将input转换成一个原始值或者报错.当input为一个原始值的类型时,那么不需要参考perferredType直接就会返回这个值.但是如果input是一个对象值呢? 除了Date类型的对象preferedType被设置为String(Date对象更期望获取转换后的字符串),其余的都会被设置为Number.
perferredType=Number
- 调用该对象的
valueOf()方法,如果valueOf()返回的是一个原始值,则返回这个原始值 - 调用该对象的
toString()方法,如果toString()返回的是一个原始值,则返回这个原始值 - 否则,抛出
TypeError异常
perferredType=String
- 调用该对象的
toString()方法,如果toString()返回的是一个原始值,则返回这个原始值 - 调用该对象的
valueOf()方法,如果valueOf()返回的是一个原始值,则返回这个原始值 - 否则,抛出
TypeError异常
Object.prototype处于原型链的最顶端,它的toString()和valueOf()方法都会被Object的派生对象所继承,当然也可以更改.
valueOf
Number|String|Boolean => number|string|boolean,即Number、String、Boolean类型的对象通过valueOf()转换成各自的原始值,即Number => num; String=>str; Boolean => boolDate => number,Date类型的对象通过valueOf()转换成数字Date => num- 其余对象返回的均为
this,即对象本身.
toString
Number|Boolean|String|Array|Date|RegExp|Function这几种构造函数生成的对象,通过toString()转换成相应的字符串形式.(自己封装的toString方法)即Number => 'num'; Boolean => 'bool'; Array => arr.join(,);String => 'str';Function => JS源码字符串; Date => 可读时间字符串;RgeExp => 'regexp'- 其他类型的对象返回该对象的类型(继承的
Object.prototype)Object => [object Object] Null,Undefined调用报错
ToNumber
ToNumber(input)将输入的值转换为数字
- Undefined:
Undefined => NaN - Null:
Null => +0 - Boolean:
true => 1 fale => 0 - Number: 结果等于输入的参数
- String:
str => Number(str); Number('') => 0; Number(str) => NaN - Object:
obj => ToPrimitive(obj,Number)
ToString
ToString(input)将输入的值转换为数字
- Undefined:
Undefined => 'undefined' - Null:
Null => 'null' - Boolean:
true => 'true' false => 'false' - String: 结果等于输入的参数
- Number:
num => 'num'(一般情况) - Object:
obj => ToPrimitive(obj,String)
转换规则
涉及+、==引起的隐式转换主要根据运算符的执行顺序和优先级来决定,这里+和==都是按照从左到右来计算
{} + {} => '[object Object][object Object]'
+号 运算符可以进行数字和字符串的计算, 那么就需要将{}转换成原始值- 默认对象(除Date)都是
ToPrimitive(input,Number),则通过调用valueOf() => this得到的还是{},而非原始值,依然不能进行操作计算 - 则调用
toString() => [object Object],得到的是原始值,可以进行操作 - 获得
[object Object][object Object]
2 * {} => NaN
*只能针对num原始值计算,那么就需要将{}转换为num原始值{}默认ToPrimitive(input,Number),调用valueOf() => this,获取{},依然不是原始值- 调用
toString() => [object Object],此时已经是原始值,但是仍然不是num,那么就需要按照ToString 将[object Object]转换为数字NaN 2 * NaN => NaN
[] == ![] => true
- 首先将
[]转化为原始值,ToPrimitive(input,Number)调用valueOf() => this,得到[]依然不是原始值,不能操作 - 调用
toString() => '',获得原始值 []转换为布尔值获取true,![]执行逻辑非操作,返回布尔值,![] => false- 此时
'' == false不能进行比较就需要将他们转为数字0 == 0 => true
const a = {
i : 1,
toString(){
return this.i ++
}
}
a == 1 && a == 2 && a == 3 => true
- 定义了对象a和重写了
toString方法 a == 1时,a不是一个原始值ToPrimitive(input,Number),调用valueOf() => this,得到a对象不是原始值- 于是调用
toString(),因为a重写了toString方法,在toString时执行this.i ++操作返回this.i => 1,同时this.i +1 = 2,因此得到原始值1,a == 1 => true - 同理
a == 2 => true; a == 3 => true=>true
== 和 +
x == y- 同类型:原始值,当 x 和 y,直接比较,
NaN !== NaN === Object.is(NaN,NaN);对象值, x和y是同一引用时相等,否则不相等 - 不同类型: x 和 y中存在
String则转换为ToNumber;如果存在Boolean则转换为ToNumber;如果存在Object,则通过ToPrimitive转换为原始值,再通过ToNumber进行比较
- 同类型:原始值,当 x 和 y,直接比较,
x + y- 原始值:x 和 y中存在
String类型则通过ToString转换后操作;否则通过ToNumber转换后操作 - 对象值:通过
ToPrimitive后转换成原始值进行操作
- 原始值:x 和 y中存在