面试题:a==1&&a==2&&a==3什么时候为true

@07 July 28, 2024

一、问题

给定一个函数:

const isTrue = a => a == 1 && a == 2 && a == 3

试问:当isTrue传入什么样的a时,isTrue返回的值可以为true?

答:

isTrue({
	v: 0,
	toString(){
		return ++this.v
	}
})
//或者
isTrue({
	v: 0,
	valueOf(){
		return ++this.v
	}
})

二、解释

a == 1 && a == 2 && a == 3看出,a既等于1又等于2又等于3,明显不是一个常量,所以排除基本数据类型(Number、Boolean、String等)。可以肯定a是一个可变的值,每次我们去访问它的时候,一开始我们去访问它的时候,它的值为1,接着递增为2、3。那怎么去实现呢?我们可以看到a的右边是数字类型的,如果a是一个对象,引擎将调用该对象valueOf方法将它转为原始值,因此我们可以重写这个方法,返回让它第一次返回1,第二次返回2,第三次返回3。这样一来a == 1 && a == 2 && c == 3 就为true了。因此可以定义一个对象a:

const a = {
	v: 0,
	valueOf(){
		return ++this.v
	}
}

为什么重写toString也可以?

因为如果没有valueOf,那就会调用toString方法

三、本题涉及几个JS的语法知识

  1. 原始值的定义

    除了对象以外,所有类型都定义了表示在语言最低层面的不可变值。我们将这些值称为原始值。(参考:JavaScript 数据类型和数据结构 - JavaScript | MDN (mozilla.org)

  2. “==“的语义(参考:相等(==) - JavaScript | MDN (mozilla.org))

    1. 等号两边类型相同
      1. 对象 → 比对引用
      2. 字符串、数字、布尔值、大整型 → 比对值
      3. 符号(Symbol)比对是否是同一个Symbol
    2. null和undefined比对为true
    3. 非原始值的操作数会被转换为原始值。
    4. 数字与布尔值比对时,1会被转为true非1被转为false
    5. 数字和字符串比对时,字符串会被转为数字,如果字符串不是合法的数字,就会转为NaN
  3. 对象的toString和valueOf方法

    1. toString表示将对象转为字符串
    2. valueOf表示将对象转为基本数据类型
    3. 在进行类型转换时
      1. 如果要转换为数字类型或基本数据类型,会优先调用valueOf方法,没有再调用toString方法。
      2. 转换为字符串类型时,会优先调用toString方法,没有就调用原生的toString方法(未被重写的toString,如对象返回”[object Object]“)

    只重写了valueOf时:

     	const obj1 = { valueOf: () => 'valueOf' }
      console.log(obj1 + 100);     //输出:valueOf100
      console.log(new Error(obj1)) //输出:Error: [object Object]
      console.log(`${obj1}`);      //[object Object]
      console.log(String(obj1));   //输出:[object Object]
      console.log(obj1 == 'valueOf', obj1 == 'toString'); //true false
      console.log(obj1 + obj1);       //输出:valueOfvalueOf
    

    只重写了toString时:

     	const obj2 = { toString: () => 'toString' }
      console.log(obj2 + 100);     //输出:toString100
      console.log(new Error(obj2)) //输出:Error: toString
      console.log(`${obj2}`);      //输出:toString
      console.log(String(obj2));   //输出:toString
      console.log(obj2 == 'valueOf', obj2 == 'toString'); //false true
      console.log(obj2 + obj2);       //输出:toStringtoString
    

    重写了valueOf和toString时:

      const obj3 = { valueOf: () => 'valueOf', toString: () => 'toString' }
      console.log(obj3 + 100);     //输出:valueOf100
      console.log(new Error(obj3)) //输出:Error: toString
      console.log(`${obj3}`);      //输出:toString
      console.log(String(obj3));   //输出:toString
      console.log(obj3 == 'valueOf', obj3 == 'toString'); //true false
      console.log(obj3 + obj3);       //输出:valueOfvalueOf
    

参考链接:

  1. https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/toString
  2. https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf
  3. toString()和valueOf()函数调用和优先级-腾讯云开发者社区-腾讯云
  4. https://www.cnblogs.com/peakleo/p/6248242.html
  5. 彻底了解toString和valueOf区别-CSDN博客

  • 36
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值