隐式类型转换
一、类型转换
所谓类型转换就是将一种数据类型转换为另一种数据类型。在编译或者运行时,会发生自动转换类型,这种称之为隐式转换,当我们使用一些其他的方法来进行转换时,这种就叫做显示转换。
二、隐式转换
为什么会出现隐式转换?
首先我们所知道的就是Javascript是一种弱类型语言,这就意味着他会自动转换数据类型,来使得数据之间更加容易进行比较和操作
1.装箱和拆箱
1.1装箱
装箱意味着将原始类型转换为引用类型,即创建包装类型。在JS当中引入了三种特殊的类型Number、String、Boolean,我们称其为包装类型。
什么是包装类型?
使用new操作符创建一个原始类型实例的方式就叫做包装类型。
1.2拆箱
将引用类型转换为原始数据类型,在拆箱过程中会遵循ECMAScript规定的toPrimitive原则,对引用类型进行转换。
toPrimitive函数
toPrimitive方法是在引用类型转换为原始类型的过程中js自动帮我们调用的方法
toPrimitive方法中会按条件调用[Symbol.toPrimitive];valueOf();toString()中的一种或多种方法帮助我们将引用类型转换为原始类型。
toprimitive函数执行的一般顺序: ● 若存在[Symbol.toPrimitive]属性,则优先调用并返回 ●
否则,将优先调用valueOf方法,返回原始类型的值 ●
若不存在valueOf属性或返回类型不是原始类型,则调用toString方法,返回原始类型的值 ●
若也不存在toString属性或返回类型不是原始类型,则抛出异常TypeError
简单来说如果值是基本类型,那么就会直接返回值本身(valueOf()方法返回对象的原始值、toString()方法是对象的字符串表示)。如果是引用类型那么就会调用toprimitive()方法。
2.数据类型转换
2.1隐式转换
转换规则:
● String与Number:字符串和数字进行运算时,jS会将字符串默默转换为数字类型(+号除外)
● Boolean与其他:与其他类型运算时会将布尔值默默的转换为数字类型(true为1、false为0)
● Object与原始数据类型进行转换:对象与原始数据类型进行转换时,会将对象默默转换为原始数据类型
2.1.1 Number
//boolean类型转换
console.log(+true) // 1
console.log(+false) // 0
//数组
console.log(+[]) // 0
console.log(+[5]) //5 先调用valueOf()方法返回自身,再调用了toString()方法转换为"5",隐式转换为5
console.log(+[1,2,3]) // NaN 数组是对象类型,因此首先调用 valueOf() 方法。但数组的 valueOf() 返回自身(仍是对象),于是继续调用 toString() 方法。转换为"1,2,3"所以会转换为NaN
//对象 console.log(+{}) //NaN console.log(+{name:"张san",age:12})//NaN
//字符串
console.log(+"1234") //1234
console.log(+"1234px") //NaN
//undefined
console.log(+undefined) //NaN
2.1.2 String
//boolean类型转换
console.log(true+"") //"true"
console.log(false+"") //"false"
//数组
console.log([]+"")//0
console.log([1,2,3]+"")//1,2,3
//对象
console.log({}+"")//"[object Object]" 对象 {} 需要转换为原始值。转换规则为:调用 valueOf(),返回对象本身(非原始值)。继续调用 toString(),默认返回 "[object Object]"。
console.log({name:"egg",age:12}+"")//"[object Object]"
//undefined
console.log(undefined+"")//undefined
2.2 各种运算符
2.2.1 “-”、“*”、“/” 三种运算符
在四则运算符中的"-“、”*“、”/" ,这三种运算符可以非数字类型的数据转换为数字类型
//boolean
console.log(1-false) //1 false=>0
console.log(1-true) //0 true=>1
console.log(1/true) //1 true=>1
console.log(1*true) //1 true=>1
//数组
console.log(1-[]) //1 []=>0
console.log(1-[2]) //-1 [2]=>2
console.log(1-[2,2,3]) //NaN [2,2,3]=>"2,2,3"
//对象
console.log(2-{})//NaN {}=>NaN
console.log(2-{name:"Sunny",age:12}) //NaN {name:"Sunny",age:12}=>NaN
//字符串
console.log(2-"1")//1 1=>1
console.log(2-"1.5")//0.5 1.5=>1.5
console.log(2-"2.1px") //NaN "2.1px"=>NaN
//对象
console.log(2-{})//NaN {}=>NaN
//undefined
console.log(2-undefined)//NaN undefined=>NaN
2.2.2 "+"运算
'+'运算需要视情况而定,如果是数字类型与数字类型相加,那么就是加的意思,如果是字符串使用加运算符,那么就是拼接的意思。
//其中一边为字符串类型
console.log("123:"+456) //结果:123456 如果一边是String类型,那么另一边也会转换为String类型,做字符串拼接
//其中一边为数字类型
console.log(123+false) //结果:123 如果一边是数字类型,另一边是原始数据类型(String类型除外),那么就会转换为数字类型,做加法运算。
console.log(123+{})//结果:123[object Object] 如果一边是数字类型,另一边是引用类型,那么都转换为String类型进行拼接
//引用类型
console.log([1,2,3]+[4,5,6]) //结果:1,2,34,5,6 如果两边都是引用类型,那么就会继续遵循toPrimitive原则
- "=="运算符(判断两边的内容是否一致)
● 基本数据类型(原始数据类型)
//1.NaN与任何数据类型进行比较都会返回false
console.log(NaN==123) //false
console.log(NaN==NaN) //false
console.log(NaN==[]) //false
console.log(NaN=={}) //false
console.log(NaN==true) //false
console.log(NaN=='123') //false
console.log(NaN==undefined) //false
console.log(NaN==null) //false
//2.number类型与String类型
console.log(1=='1') //true Number与String类型进行比较的时候会将字符串转换为数字类型
console.log(1=='abc')//false abc=>NaN
//Undefined 与 null
console.log(undefined == null) // true
console.log(undefined == 123) // false
console.log(undefined == true) // fasle
console.log(undefined == '123') // false
console.log(undefined == []); // fasle
console.log(undefined == {}); // fasle
console.log(null == 123) // false
console.log(null == true) // fasle
console.log(null == '123') // false
console.log(null == []); // fasle
console.log(null == {}); // fasle
//布尔类型
console.log(true == 123) // fasle true => 1
console.log(true == 1); //true true => 1
console.log(true == "1"); //true true => 1, "1" => 1
console.log(true == "true"); //false true => 1, "true" = > NaN
● 引用数据类型
引用与引用相对比,比较两个原始数据类型在堆内存(栈空间中存放的地址)中是否是一致的,如果一致那么会返回true,否则返回false
//引用数据类型与引用数据类型相比较
let obj1={name:"张三",age:29}
let obj2=obj1
let obj3={name:"张三",age:29}
console.log(obj1 == obj2) //true
console.log(obj1 == obj3) // false
引用与原始数据类型比较,引用类型会遵循toPrimitive原则,将引用数据类型转换为原始数据类型,再按照原始数据类型比较的方式进行比较
console.log(0=={}) //false {}=> [object, Object]=>NaN
console.log(0==[]) //true []=>""=>0
三、总结
//测试:
//从左向右执行:
/*100+0(false=>0)=100 100+30=130 130+null(null=>0)=130 130+undefined(undefined=>NaN)=NaN
NaN(NaN=>"NaN")+"Tencent"=NaNTencent NaNTencent+[]([]=>"")=NaNTencent
NaNTencent+null(null=>"null")=NaNTencentnull
NaNTencentnull+9(9=>'9')=NaNTencentnull9
NaNTencentnull9+false(false=>"false")=NaNTencentnull9false */
console.log(let result = 100 + false +30 + null + undefined + "Tencent" + [] + null + 9 + false) //NaNTencentnull9false