(a== 1 && a ==2 && a==3)可能为true吗?

(a== 1 && a ==2 && a==3)可能为true吗?

前言

  • 最近在网上看到一个面试题:(a== 1 && a ==2 && a==3)有可能返回true吗?答案是可以的,下面来具体讲解一下。

valueOf和toString

  • 这个问题的一个关键点就是在于利用==双等号工作原理,=====有什么区别呢?最主要的就是用==的时候会涉及到类型转换,如果双等号两边数据类型不同会尝试将他们转化为同一类型。基础数据类型之间的转换是比较简单的,这里来说一下对象类型在使用==时产生的隐形转换。
  • valueOf和toString这两个方法是每个对象都自带的(继承自Object原型),我们先定义一个简单的对象然后调用他的这两个方法来看下结果:
    (a== 1 && a ==2 && a==3)可能为true吗?
  • 可以看到toString返回一个字符串"[object Object]",valueOf则是直接返回对象本身,而c=="[object Object]"也为true则说明了在隐式转换的过程中,调用了c的toString方法。

实现

  • 到这里我们只要重新定义一下变量a,重写它的toString方法就可以实现我们要达到的目的了:
let a = {   i: 1,   toString () {     return a.i++   } }  if(a == 1 && a == 2 && a == 3) {   console.log('Hello World!'); } // 输出Hello World!  
  • 这里说下具体的过程:执行a==1时,js引擎会尝试把对象类型a转化为数字类型,首先调用a的valueOf方法来判断,不行则继续调用toString方法,然后再把toString返回的字符串转化为数字类型再去和a作比较(这里我重写了toString就直接返回的数字类型的结果,正常情况toString返回的字符串)。
  • 所以每一次使用==判断都会调用一次a的toString方法,返回i属性的值,然后使a的i属性加1,这样最后的判断结果自然就为true了。
  • 其实重写valueOf方法也可以实现,而且转化时会优先调用valueOf方法:
var c = {   toString () {     console.log('toString')   },   valueOf () {     console.log('valueOf')   } } c == 1 // console输出'valueOf'  

结语

  • 这个问题看起来是解决了,但其实在实际项目中去重写原生对象的toStringvalueOf方法是很不应该的,比如toString本来是一定会返回一个字符串结果的,重写后返回其他类型反而容易出问题。

本文来自,本文观点不代表PmTemple立场,转载请联系原作者。原文链接:

发表评论

电子邮件地址不会被公开。 必填项已用*标注

联系我们

185-1614-2515

在线咨询:点击这里给我发消息

邮件:admin@pmtemple.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code