0
点赞
收藏
分享

微信扫一扫

什么时候 a == 1 && a == 2 && a == 3 为 true?


说明

在网上看到的一个面试题:什么时候 ​​a == 1 && a == 2 && a == 3​​ 为 true?

觉得很有趣,记录一下。(当然我想不出来​​_(:3」∠)_​​).

分析

关于要这个表达式成立, ​​a == 1 && a == 2 && a == 3​​​ 的每一个条件都要为 ​​true​​.

1、显然,如果 每次调用 变量 a ,a 的 值都固定不变,肯定没戏。

2、所以,要想使 ​​a == 1​​​、​​a == 2​​​、​​a == 3​​​ 都为 ​​true​​,就是只能每次调用 a 时,a 的 值每次 加 1。

注意

当两个类型不同时进行 == 比较时,会将一个类型转为另一个类型,然后再进行比较。

1、Object类型与Number类型进行比较时,Object类型会转换为Number类型。

对象转换为 ​​Number​​​ 时,会尝试调用 ​​Object.valueOf()​​​和​​Object.toString()​​来获取对应的数字基本类型。

2、数组调用​​toString()​​​会隐含调用​​Array.join()​​方法。

解法一:对象类型转换

1、覆盖自定义对象的 valueOf() 方法

​​Object.prototype.valueOf()-参考文档​​

Object 的 valueOf() 方法会返回指定对象的原始值。

不同类型对象的valueOf()方法的返回值。

对象

返回值

Array

返回数组对象本身。

Boolean

布尔值。

Date

存储的时间是从 1970 年 1 月 1 日午夜开始计的毫秒数 UTC。

Function

函数本身。

Number

数字值。

Object

对象本身。这是默认情况。

String

字符串值。

Math 和 Error 对象没有 valueOf 方法。

代码实现:

var val = 0
var a = {
valueOf: function() {
console.log('valueOf-->', val)
return ++val
}
}
// 分开打印
console.log('Number-->', Number(a))
console.log('Number-->', Number(a))
console.log('Number-->', Number(a))

/* 输出结果:
valueOf--> 0
Number--> 1
valueOf--> 1
Number--> 2
valueOf--> 2
Number--> 3
*/

// 或者直接打印
console.log(a == 1 && a == 2 && a == 3) // 输出:true

2、覆盖自定义对象的 toString() 方法

代码实现:(跟上面的有点类似)

var a = {
i: 1,
toString: function() {
console.log('toString-->', a.i)
return a.i++
}
}
// 分开打印
console.log('Number-->', Number(a))
console.log('Number-->', Number(a))
console.log('Number-->', Number(a))

/* 输出结果:
toString--> 1
Number--> 1
toString--> 2
Number--> 2
toString--> 3
Number--> 3
*/

// 或者直接打印
console.log(a == 1 && a == 2 && a == 3) // 输出:true

代码分析:

object --> number (引用类型转换为原始类型)

  • 1、先调用object的​​valueOf​​方法,如果为原始值,则return,否则第2步
  • 2、调用object的​​toString​​方法,如果为原始值,则return,否则第3步
  • 3、抛出​​TypeError​​异常

如果到这里还是不怎么清晰的话:(请看下图:里面涉及​​ToPrimitive函数​​)

由Dry同学整理提供下图

什么时候 a == 1 && a == 2 && a == 3 为 true?_类型转换

解法二:数组类型转换

var a = [1, 2, 3];
a.join = a.shift; // 核心操作转移

console.log(a == 1 && a == 2 && a == 3);

// valueOf --> toString --> join

代码分析:

上面代码 ​​a.join = a.shift;​​ 数组 a 的 join 被 shift 方法覆盖。

而数组调用 ​​toString()​​​ 会隐含调用 ​​Array.join()​​ 方法。

从而达到一个目的:对数组 ​​[1, 2, 3]​​​ 执行 ​​shift​​ 方法操作。

解法三:创建属性 defineProperty 的 get

​​defineProperty-参考文档​​

var val = 0;
Object.defineProperty(window, 'a', {
get: function() {
return ++val;
}
});
console.log(a == 1 && a == 2 && a == 3);


举报

相关推荐

0 条评论