由‘==’和‘===’引出的js的隐式转换问题

2018-6-1    周周

‘==’和‘===’都是Javascript中的比较运算符,都是比较运算符两边是否相等。对于‘==’和‘===’的区别,大家也都知道:

  ‘==’仅仅是比较运算符两边的数值是否相等,如果数值相等则返回true;‘===’不仅会判断运算符两边的数值是否相等,并且还会判断两边的类型是否相等,只有数值和类型都相等才会返回true。虽然知道以上的判断依据已经能解决绝大数此类问题,但是如果往其中深究来说,会有同学问:在比较的时候‘===’先判断类型,如果类型不同就直接返回false,这个没什么问题。但是如果是‘==’比较两个不同类型的数据时,具体是怎么进行计算判断的呢?

 既然是不同类型进行比较,肯定最终参与比较的结果必须是同一个类型的,因此JS会存在一个隐式转换的问题,并且很多JS的隐式转换很难通过console.log()等方法直观的观察到,因此很多初学者会对JS的隐式转换感到疑惑。

 首先让我们回忆一下,咱们的JS中一共有哪些数据类型?

       六大数据类型
       基本数据类型(简单数据类型)
       number 数值型(NaN)
       string 字符串
       boolean 布尔型
       undefined 未定义
       null 空引用
       引用数据类型(复杂数据类型)
       object

       JS基础中,我们学习到咱们的JS中一共有六种数据类型,分为基本数据类型(简单数据类型)和引用数据类型(复杂数据类型),不同类型的值进行比较的时候,存在隐式转换的问题,咱们通过‘==’来验证一下JS隐式转换的情况。

       1.我们首先来看看下列的语句计算结果:

console.log(NaN==true);//false
console.log(NaN==false);//false
console.log(NaN==0);//false
console.log(NaN==1);//false
console.log(NaN==NaN);//false

       由上面的例子可以看出,NaN属于Number数据类型中一个特殊情况,如果‘==’两边同为Number数据类型的数字,很直观的可以看出值是否相同一眼就可以看出结果,但是作为Number类型的特殊情况,NaN在进行比较的时候,也会有特殊的结果:如果 x 或 y 中有一个为 NaN,则返回 false;

       2.我们继续看看下列的语句计算结果:

console.log(null == undefined); //true(特殊情况)---------------------------------
console.log(null == ''); //false
console.log(undefined == ''); //false

      在上述例子中,引出了一个null,null是一个简单数据类型,它的意义就是一个空应用,但是你如果通过console.log(typeof null) 来打印结果的时候却发现,结果竟然是object?此时你可能会怀疑人生,然后疯狂的翻阅之前学习的资料,因为object明明是一个复杂数据类型,怎么会在判断null这个简单数据类型的类型时打印出来呢?其实,这个问题属于一个历史问题。咱们学习的JS在发展过程中是通过ECMAScript来确定规范的,每年都会有新的规定和规范提出,在JS的发展过程中,null一开始的作用就是用来指向一个空地址,让开发者在创建数据的时候,先用null赋值给还未给值的对象用于标准初始化。但是其实咱们开发过程中很少用到,但是这个仍作为规范留了下来。又因为typeof是根据数据的前几位判断数据类型的,null相当于空指针,前几位是地址的格式,所以判断结果就为object。又因为undefined值是派生自null值的,因此ECMA-262规定对他们的相等测试要返回true。所以这一情况判断的条件为:如果 x 与 y 皆为 null 或 undefined 中的一种类型,则返回 true(null == undefined // true);否则返回 false(null == 0 // false);

       3.请看下列例子:

console.log(true == '123'); //false
console.log(true == '1'); //true
console.log(false == '0'); //true
 
console.log(true == !0); //true
 
console.log([] == []); //false
console.log([] == ![]); //true 比较地址 ------------------------------------------------
var a = c = [];
var b = [];
console.log(a == b); //false
console.log(a == !b); //true
console.log(a == c); //true
 
console.log(Boolean([]) == true); //true
console.log(Number([]) == 0); //true
console.log(Number(false) == 0); //true

       其实比较的逻辑为:如果 x,y 类型不一致,且 x,y 为 String、Number、Boolean 中的某一类型,则将 x,y 使用 Number 函数转化为 Number 类型再进行比较;

      使用Number函数可以将其他的数据类型转变为Number类型,这一同为Number类型的数据,对比起来就会变得十分简单。值得注意的是在上述的例子中,两个空数组进行比较,结果返回的结果仍然为false,这个是怎么回事呢?其实这个很好理解,因为数组也是对象的一种,是复杂数据类型,所以用变量储存对象时储存的其实是地址。对象的内容相同,但是储存在堆区的位置不同,所以地址也是不同的,所以在判断的时候返回的是false。

      其实在JS中还有很多的隐式转换情况,以上只是针对于‘==’的隐式转换情况,对于这些问题,在实际开发过程中,需要作为开发者不断的学习和积累,这也是咱们作为开发者的一个要求之一。

分享本文至:

日历

链接

blogger

蓝蓝 http://www.lanlanwork.com

存档