目录
1.什么是隐式转化?
在JavaScript中,当运算符在运算时,如果运算符两边数据不统一数据类型,计算机底层CPU就没办法计算。所以编译器就会自动将运算符两边的数据做一个数据类型转化,转成一样的数据类型再进行计算(一般转化为数字型,因为计算机底层是以二进制数据进行计算)。这种无需程序员手动操作,编译器自动转换的方式就称为隐式转换。
eg:2 > "3" 结果为?
分析:"3"转换为数值型为 3,2 > 3结果为false
2.隐式转换规则
1.转换为string类型: + (字符串连接符)
若运算符+ 两端都是数值型,就是正常的加法运算
若运算符+两端含有字符串型,就会把数据类型转为字符串,再进行拼接
2.转换为number类型:++ -- 算术运算符(+,-,*,/,%,**),关系运算符(>,<,>=,<=,==,!=)
3.转换为boolean类型: !,!!(逻辑非运算符)
注意点: + 它既是连接符,也是运算符。当 + 两边都有值,且至少一个值是字符串类型时,就会转换为字符串类型,再进行字符串拼接。当只有 + 后面的值时,例如:+"456";等同于
Number("456"),会将字符串转换为数字456.
var a = +"123"; console.log(a); // 123 console.log(typeof a); // number console.log(+undefined); //NaN console.log(+null); //0 console.log(+true); //1 console.log(+false); //0 console.log(+'111'); //111 console.log(+'11a'); //NaN
3.不同类型 比较 或 运算 时的隐式转换规律
如上图:任意两种不同类型的值进行比较时(针对的是类型不同的),会按照上图方式进行相应的类型转换,例如:对象和布尔值比较的话,对象-->字符串-->数值,布尔值-->数值。然后两个数值进行比较。
那么具体对象是怎么转换为数值型的呢?
4.对象 进行数据类型转换的过程
1.先调用对象的 Symbol.toPrimitive 这个方法,如果不存在这个方法(结果是undefined),目前已知的只有
new Date()
有这个方法,2.再调用对象的 valueOf()获取原始值/基本数据类型,如果获取的不是原始值/没有得到基本数据类型,
3.再调用对象的 toString() 把其变成字符串
4.最后再把字符串调用 Number() 转换为数字 (结合 5.一些基本规律 来看)
eg: 结合例子理解:
console.log([] + 1);
// [].valueOf()没有原始值,再调用 [].toString()得到 "",
//字符串遇到`+`运算符可以进行拼接,就不需要转成数字 => "1"
console.log([2] - true);
// `[].valueOf()`没有原始值,再调用`[].toString()`得到`"2"`,
//再调用`Number("2")`得到数字2。true直接调用`Number(true)`得到1。最后2 - 1 => 1
console.log({} + 1);
// `{}.valueOf()`没有原始值,再调用`{}.toString()`得到"[object Object]",
//遇到`+` 号进行字符串拼接 => "[object Object]1"
console.log({} - 1);
// {}.valueOf()没有原始值,再调用`{}.toString()`得到"[object Object]",
//再调用`Number("[object Object]")`得到NaN,最后NaN - 1 => NaN
5.一些基本规律
含字母(或其它字符 ,例如:","等)的字符串转换为数字型时,结果为NaN (NaN属于数字型),只含数字的字符串转为数字型时会转为该数字。
eg:举例说明 调用Number()函数 console.log(Number("undefined")); //NaN console.log(Number("null")); //NaN console.log(Number("NaN")); //NaN console.log(Number("true")); //NaN console.log(Number("false")); //NaN console.log(Number("[object Object]")); //NaN //特殊 console.log(Number("")); //0 console.log(Number("123aaaa")); //NaN console.log(Number("aaa123aaaa"));//NaN console.log(Number([2,3])); //NaN 调用toString()得到"2,3" 含有其它字符,所以转为NaN //只含数字的字符串 console.log(Number("1")); //1 console.log(Number("0")); //0 console.log(Number("-1")); //-1 //注意点: Infinity(极大值) 和 -Infinity(极小值)都是属于数字型 console.log(Number("Infinity")); //结果为数字型数据 Infinity console.log(Number("-Infinity")); //结果为数字型数据 -Infinity
其它类型转换为数字型:
console.log(Number(true)); //1 console.log(Number(false)); //0 console.log(Number(null)); //0 console.log(Number(undefined));//NaN 重点
其它类型转换为布尔类型:
只有 0 ,NaN , null, undefined ,空字符串' ',false转为布尔类型时为false,其余情况转换为布尔类型都是true。且没有特殊情况
console.log(Boolean(0)); //false console.log(Boolean(NaN)); //false console.log(Boolean(null)); //false console.log(Boolean(undefined)); //false console.log(Boolean("")); //false console.log(Boolean(false)); //false
6."==" 相等/宽松相等/抽象相等
1、如果一个值是null,另一个是undefined,则它们相等。
2、如果一个值是数字,另一个是字符串,先将字符串转换为数字,然后使用转换后的值比较。
3、如果其中一个值是true,则将其转换为1再进行比较。如果其中一个值是false,则将基转换为0再进行比较。
4、如果一个值是对象,另一个值是数字或字符串,则将对象转换为原始值,然后再进行比较。对象通过toString()方法或valueOf()方法转换为原始值。JavaScript核心的内置类首先尝试使用valueOf(),再尝试使用toString(),除了日期类,日期类只使用toString()转换。那些不是JavaScript语言核心中的对象则通过各自的实现中定义的方法转换为原始值。
5、其他不同类型之间的比较均不相等.
一些特别的例子:
console.log(+0 == -0); //true
console.log(null == undefined); //true
console.log(NaN == NaN); //false
console.log(NaN != NaN); //true
console.log(undefined == 0); //false 因为undefined转为数字型为NaN
console.log(null == 0); //false 重点且易错 看下面案例eg6
7."===" 全等/严格相等
基本数据比较类型和值,引用数据比较 类型/堆地址,是否相同。
1、如果两个值类型不相同,则它们不相等。
2、如果两个值都是null或者都是undefined,则它们不相等。
3、如果两个值都是布尔值true或false,则它们相等。
4、如果其中一个值是NaN,或者两个两个值都是NaN,则它们不相等。NaN和其他任何值都是不相等的,包括它本身!!!通过!x==x来判断x是否为NaN,只有在x为NaN的时候,这个表达式的值才为true。
5、如果两个值为数字,且数值相等,则它们相等。如果一个为0,另一个为-0,则它们同样相等。
6、如果两个值为字符串,且所含的对应位上的16位数完全相等,则它们相等。如果它们的长度或内容不同,则它们不等。两个字符串可能含义完全一样且所显示出手字符也一样,但具有不同编码的16位值。JavaScript并不对Unicode进行标准化的转换,因此像这样的字符串通过"==="和"=="运算符的比较结果也不相等。
7、如果两个引用值同一个对象、数组或函数,则它们是相等的。如果指向不同的对象,则它们是不等的。尽管两个对象具有完全一样的属性
8.案例
eg1:console.log([12] == 12); 结果为?
分析:结果为 true。 因为[12] 和 12 属于不同数据类型,先要转换为相同数据类型。
数组对象[12]按照对象转换规则,最后转为12, 所以 12 == 12 结果为true
eg2:"true" == true 结果为 ?
分析:不同数据类型进行比较,会先转化为相同数据类型
"true" 转化为数字型为 NaN
true 转化为数字型为 1
所以 结果为false
eg3:为什么两个的结果都是true?(易错题) (结合5.一些规律来看)
console.log([] == false); // true
console.log(![] == false); //true
分析:
数组对象[ ],没有Symbol.toPrimitive 这个方法,再调用valueOf(),没有得到基本数据,再调用toString();得到空字符串" ",再Number(""),结果为0,而false转为数字型也是0
所以 console.log([] == false); 结果为true
,
逻辑非!的操作步骤是: 先把[ ]转为布尔值,结果为true,再让其取反为false,所以就是false == false 结果为true。
eg4:console.log([[]] == false); 结果为?true
分析:结果为true ;因为数组对象[[]]转换为字符串结果为"",再转为数字型,结果为0,false转为数字型结果为0 ,所以true
console.log([[]].valueOf()); //[Array(0)]
console.log([[]].toString());//""
console.log(Number("")); //0
但是: console.log([[1]] == false); 结果为false
console.log([[1]].valueOf()); //[Array(1)]
console.log([[1]].toString());//"1"
console.log(Number("1")); //1
eg5:console.log({} == {}); 结果为? false
分析:类型, 值相同时,比较堆/栈内存中的地址是否相同。每一个对象在 堆内存中地址都是不一样的,除非是同一个对象,{},{}
形式上看着是一样的,但其实是两个不同堆地址的内存空间。所以为false
eg6: console.log([] == []); 结果为? false
分析:类型, 值相同时,比较堆/栈内存中的地址是否相同
两个都是[]数组对象,但是在堆内存中地址不同,所以为false
eg7:为什么 null > 0 结果为false,null >= false结果为true,null == false,结果为false?
易错:易错认为 null == 0 结果为 true
console.log(null > 0); //false
console.log(null >= 0); //true
console.log(null == 0); //false
console.log(Number(null)); // 0
结果分析:
> / < :对比大于或小于的时候, null 会尝试转型为number 型数据, 转化之后null为0, 0>0是错误的,所以结果为 false.
>= / <= :同上,对比 大于等于 或 小于等于 的时候, 会先判断大于或小于, 这时候null 会尝试转型为number , 转化之后null为0, 0>0是错误的,但是0=0是正确的, 这是 “或” 的判断, 所以结果为 true
== :null在设计上,对比等于的时候不尝试转型. null和0不转型的话,是不会相等的, 所以null == 0结果为false.
9.常见的 "==" 关系表
一道阿里面试题:JavaScript中如果判断两个变量相等?
满分回答思路:01.使用绝对相等 "==="判断,并说明:NaN与NaN,+0和-0除外
02.或者使用ES6中object.is()方法判断,并说明与"==="相等的区别
03.了解object.is()是如何实现的?
后面学习完ES6再回来看。。。。