#js中的隐式转化
隐式转换 : 运算符在运算的时候,如果两边的数据类型不一致,则会自动转成一致后运算。
简单数据类型的隐式转换
其它类型转string : + 连接符
其它类型转number :
- 自增自减(++ --)
- 算术运算符( + - * / %)
- 关系运算符 :
>、>=、<、<=、==、!=、===、!==
其它类型转boolean : ! 逻辑非
特殊情况
- === : 全等运算符。 不存在类型转换, 先比较类型,然后比较值
- == : 比较运算符。 隐式转换规则是转成number,但是有前提条件
- x == y: 比较运算符分为五种情况
3.1 x和y 都为 null或undefined
*不会类型转换,得到固定值true
3.2 x或y 为NaN
* 不会类型转换,得到固定值false (NaN与任何数据都不等,包含自身)
3.3 x和y 都为 string,boolean,number ,且类型不一致
* 会类型转换, 会把其他类型转成number后计算
//1. === : 全等运算符(不存在类型转换)
// 严格匹配 : 数据类型 与 值 必须要同时相等
console.log('1' === 1 );//false
console.log( 1 === 1 );//true
console.log( undefined === null );//false
//2. == : 比较运算符 : 隐式转换是有前提条件的 ( x == y )
//2.1 x和y 都为 null或者undefined。
// 不会类型转换,固定返回true
console.log( Number(null) );//0
console.log( Number(undefined) );//NaN
console.log( null == null );//true
console.log( undefined == undefined );//true
console.log( null == undefined );//true
//2.2 x或y 为NaN
// 不会类型转换,固定返回false (NaN与任何数据都不等)
console.log( NaN == 0 );//false
console.log( NaN == undefined );//false
console.log( NaN == null );//false
console.log( NaN == NaN );//false
//2.3 当x或y 都为 :string,number,boolean。且数据类型不一致,此时会转换成number后运算
console.log( 1 == '1' );//true 1 == Number('1')
console.log( false == '0' );//true Number(false) == Number('0') 0 == 0
复杂数据类型的数据转换
-
x或y 为引用类型 (一个是引用类型,一个是值类型)
* 前提 : 引用类型会先调用valueOf(),然后调用toString(),再来计算 (最终变成字符串来比较)
* valueOf() : 一般引用类型,返回自身(一般忽略)
* toString() : 数组是join()字符串, 对象是固定字符串 ‘[object Object]’
-
x和y 都为引用类型。 则会比较两者地址,地址一样则为true,否则为false
// x或y 存在引用类型,则会转成 `原始值` 后比较
// 一个是引用类型,一个是基本类型
// 引用类型转原始值 : 先调用对象的valueOf() 方法获取原始值,然后调用toString() 转成字符串比较
// a. valueOf() : 可以忽略, 对象类型默认valueOf会返回自身
console.log( [10,20,30].valueOf() );// [10,20,30]
console.log( new Number(10) );//10 valueOf() 默认只会对基本包装类型有效
// b1. toString() : 数组的toString() 本质是调用join()转成字符串
console.log( [10,20,30] == '10,20,30' );//true
console.log( [] == '' );//true
console.log( [] == 0 );//true (1) [].toString (2) '' == 0 (3) 0 == 0
// b2. toString() : 对象的toString() 返回固定格式字符串 '[object Object]'
console.log( {name:'张三'} == '[object Object]');//true
console.log( {name:'李四'} == '[object Object]');//true
/* 以下是针对第四种情况的面试题的坑(入门级) */
console.log( [] == '' );//true
console.log( [] == '[object Object]' );//false
console.log( [] == 0 );//true
console.log( {} == '' );//false
console.log( {} == '[object Object]' );//true
console.log( {} == 0 );//false
/* 以下是针对第四种情况的面试题的坑(高手级) */
console.log( [] == 0 );//true
//(1) ![] 隐式规则转布尔类型 !Boolean([]) = !true = false
//(2) flase == 0
//(3) Number(false) == 0 0 == 0
console.log( ![] == 0 );//true
console.log( {} == 0 );//false '[object Object]' == 0
console.log( !{} == 0 );//true 原理同 ![] == 0 不存在调用toString() 本质是逻辑非表达式结果 与 0 比较
x或y 都为引用类型。则直接比较两者地址,地址一致则为true,地址不一致则为false
/* 以下为第五种情况面试题的坑(入门级) */
var arr1 = [10,20,30];
var arr2 = arr1;//拷贝地址 赋值
var arr3 = [10,20,30];
//虽然arr1 arr2 arr3打印时,一模一样的。但是他们对应的堆地址不同(钱一样银行卡不一样 )
console.log(arr1 == arr2);//true
console.log(arr1 == arr3);//false
console.log(arr2 == arr3);//false
/* 以下为第五种情况面试题的坑(高手级) */
console.log( [] == [] );//false 声明两个空数组,堆中地址不同
//(1)左边 ![] = !true = false
//(2)右边 [].toString = ''
//(3)false (数字0) == ''(数字0)
console.log( ![] == [] );//true
console.log( ![] == ![] );//true 两个逻辑非表达式比较 !true == !true false == false
//原理同上
console.log( {} == {} );//false
//(1)左边 !{} = !true = false
//(2)右边 {}.toString = '[object Object]'
//(3) false (数字0) == '[object Object]' (数字NaN)
console.log( !{} == {} );//false
console.log( !{} == !{} );//true
//以下为特殊情况
// null是原型链终点, 底层是堆地址起点 0x0000
console.log( null == 0);//false null不会转换 ,会直接用地址 和 0 比较
//以上五种情况 只是对 == 运算符生效。 其他的比较运算符还是转number
console.log( null >= 0);//true Number(null) >= 0 0 >= 0
console.log( null <= 0);//true Number(null) <= 0 0 <= 0