JS容易出现误区的运算符
相等运算符
==
====在比较前将两个被比较的值转换为相同类型。在转换后(等式的一边或两边都可能被转换),最终的比较方式等同于全等操作符===的比较方式。
记住下面这张表即可,特别注意的是Boolean值和String值被比较时,会ToNumber转换, Object会根据情况做隐式转换。

Object.is(A,B)
Object.is(A,B)Object.is()主要是和===在NaN、+0、-0 上面有区别,其他场景一样。
Object.is()判断NaN是相等的,+0和-0是不相等的,刚好和 ===相反
Object.is(-0 , +0) // false
-0 === +0 // true
Object.is(NaN , NaN) // true
NaN === NaN // false
隐式转换
[1,2] == '1,2' // true下面单独聊一聊隐式转换
隐式转换ToPrimitive()
ToPrimitive()默认用法:
ToPrimitive(input [,PreferredType]),(ToPrimitive方法可被修改)如果input是基本数据类型,则不转化,如果是object, 则按照下面方式转化
如果没有传入
PreferredType参数,则让hint的值为'default'否则,如果
PreferredType值为String,则让hint的值为'string'否则,如果
PreferredType值为Number,则让hint的值为'number'如果input对象有
@@toPrimitive方法,则让exoticToPrim的值为这个方法,否则让exoticToPrim的值为undefined如果
exoticToPrim的值不为undefined,则让
result的值为调用exoticToPrim后得到的值如果
result是原值,则返回抛出
TypeError错误
否则,如果hint的值为
'default',则把hint的值重新赋为'number'返回
OrdinaryToPrimitive(input,hint)
OrdinaryToPrimitive(input,hint)
input的数据类型是对象,hint的数据类型是字符串,并且hint的值要么是"string",要么是"number"。该抽象操作的步骤如下:
如果hint的值为'string',则
调用
input对象的toString()方法,如果值是原值则返回否则,调用
input对象的valueOf()方法,如果值是原值则返回否则,抛出
TypeError错误
如果hint的值为
'number',则调用
input对象的valueOf()方法,如果值是原值则返回否则,调用
input对象的toString()方法,如果值是原值则返回否则,抛出
TypeError错误
稍微总结一下:在没有改写或自定义@@toPrimitive方法的条件下,
如果是
Date对象求原值,则PreferredType是String,其他均为Number。PreferredType是String,则先调用toString(),结果不是原始值的话再调用valueOf(),还不是原始值的话则抛出错误;PreferredType是Number,则先调用valueOf()再调用toString()。总结来讲就是:如果是对
Date对象做隐式转化,先调用toString, 如果不是原始值的话,调用valueOf(),还不是原始值的话则抛出错误; 对其他对象做隐式转化的话,则先调用valueOf()再调用toString()。
+ - ++ --运算符
+ - ++ --运算符在加法的过程中,首先把等号左右两边进行了求原值ToPrimitive()操作,然后如果两个原值只要有一个是String类型,就把两个原值都进行转化字符串ToString()操作,进行字符串拼接;否则把两个原值都进行转化数字ToNumber()操作,进行数字相加。
+[] //0
+[0] //0
+{} //NaN
[] + [] // ""
// PreferredType是Number,则先调用valueOf()再调用toString()。 []==>[]==>""
{} + {} //"[object Object][object Object]"
//{} PreferredType是Number,则先调用valueOf()再调用toString() {}==>{}==>"[object Object]"
[] + {} // "[object Object]"
//[]==>[] ==>""
//{} PreferredType是Number,则先调用valueOf()再调用toString() {}==>{}==>"[object Object]"
// 然后字符串拼接
{} + [] // 0
// 原因在于{}在前,被当成{};直接执行了,变成了 +[],[]的原值是"",+[]需要进行toNumber转换变成了0 ,最后结果为0
++[[ ]][+[ ]]+[+[ ]]
//这个就有意思了,一开始对[][]理解错了,以为是二维数组,二维数组是name[i][j],这个才是对二维数组的调用,[][]是对前面那个一维数组的调用,数组名就是第一个[].
/*
拆分:
>> ++[[]][+[]] + [+[]] 很明显 我们知道+[]的结果是0
>> ++[[]][0] + [0] 这里我们就看到是对数组[[]]的第0位进行操作,即[]
>> ++[] + [0]
>> ([]+1) + [0]
>> (''+1) + [0]
>> '1' + [0]
>>'10'
*/下列表达式输出什么
console.log(1 + "2" + "2");
console.log(1 + +"2" + "2");
console.log(1 + -"1" + "2");
console.log(+"1" + "1" + "2");
console.log( "A" - "B" + "2");
console.log( "A" - "B" + 2);'122'
'32'
'02'
'112'
'NaN2'
NaN运算过程注意一下几点:
多个数字和数字字符串混合运算时,跟操作数的位置有关
console.log(2 + 1 + '3'); // '33' console.log('3' + 2 + 1); //'321'数字字符串之前存在数字中的正负号(+/-)时,会被转换成数字,同样,可以在数字前添加
'',将数字转为字符串console.log(typeof '3'); // string console.log(typeof +'3'); //number console.log(typeof 3); // number console.log(typeof (''+3)); //string对于运算结果不能转换成数字的,将返回
NaNconsol.log('a' * 'sd'); //NaN console.log('A' - 'B'); // NaN
&& 与 ||
&& 与 ||需要注意的是返回结果
A && B与运算,会做boolean转换,当A为false时返回A的结果,当A为true时返回B的结果,A || B或运算,当A为true时返回A的结果,当A为false时返回B的结果。
为什么0.1+ 0.2 != 0.3
在JS中,采用的是双精度版本(64位),十进制的数都是使用二进制表示的,0.1在二进制中表示为
0.1 = 2^-4 * 1.10011(0011) // (0011) 表示循环所以0.1表示的二进制与0.2表示的二进制相加,在转化为十进制就变成了0.30000000000000004。
解决方案:parseFloat((0.1 + 0.2).toFixed(10))
参考
Last updated