注册
web

面试官问我为什么 [] == ![] 为 true, 我表面冷静,实则内心慌的一批

前言



面试官问我,[] == ![] 的结果是啥,我:蒙一个true; 面试官:你是对的;我:内心非常高兴;
面试官:解释一下为什么; 我:一定要冷静,要不就说不会吧;这个时候,面试官笑了,同学,感觉你很慌的一批啊!



不必慌张,我们慢慢来!
在当今的编程领域,面试不仅是技术能力的考察,更是思维灵活性与深度理解的试金石。面试中偶遇诸如 [] == ![]  表达式这类题目,虽让人初感意外,实则深藏玄机,考验着我们对于JavaScript这类动态语言特性的透彻理解。这类问题触及了类型转换、逻辑运算以及语言设计的微妙之处,促使我们跳出日常编码的舒适区,深入探索编程语言的底层机制。接下来,我们将一步步揭开这道题目的神秘面纱,不仅为解答此类问题提供思路,更旨在通过这一过程,提升我们对JavaScript核心概念的掌握与应用能力。


首先我们来聊一下基础的东西。


1.原始值转布尔


首先是原始值转布尔


console.log(Boolean(1));//true
console.log(Boolean(0));//false
console.log(Boolean(-1));//true
console.log(Boolean(NaN));//false
console.log(Boolean('abc'));//true
console.log(Boolean(''));//false
console.log(Boolean(false));//flase
console.log(Boolean(undefined));//false
console.log(Boolean(null));//false

2.原始值转数字


console.log(Number('123'));//123
console.log(Number('hello'));//NaN
console.log(Number(true));//1
console.log(Number(false));//0
console.log(Number(''));//0
console.log(Number(' '));//0
console.log(Number(undefined));//NaN
console.log(Number(null));//0

3.原始值转字符串


console.log(String(123));//'123'
console.log(String(true));//'true'
console.log(String(false));//'false'
console.log(String(undefined));//'undefined'
console.log(String(null));//'null'

然后我们来了解一下与对象有关的转换逻辑


4. 原始值转对象


let a = new Number(1)
console.log(a);//[Number: 1]

其实也没有很特殊的,就是利用构造函数去进行显式转换即可。


5.对象转原始值


5.1 对象转布尔


屏幕截图 2024-05-21 142215.png


首先我们来到这题,最后结果会被打印,说明对象在转换为布尔值的时候,不管什么对象,都是被转换为true。


5.2 + 一元运算符


屏幕截图 2024-05-21 143018.png


我们先来了解一下,一元运算符的作用。查阅js官方文档,我们可以知道就是调用ToNumber()得到结果。而ToNumber()就是调用Number方式所调用的内置函数,因此就是强制转换为数字。我们也可以理解为+和Number()的作用是一样的。


5.3 + 二元运算符


屏幕截图 2024-05-21 150420.png


二元运算符调用ToPrimitive()方法(ToNumber中的,转换方式有差异)。


5.4 ToNumber()方法


image.png


那么这个方法具体执行过程是什么呢?我们可以看到,如果是基本数据类型转数字,我们之前已经聊到,因此不必多聊,而面对对象转数字的时候,我们会先调用ToPrimitive方法。


5.5 ToPrimitive()方法


image.png


关于这个方法,我们要看是被ToNumber还是Totring方法给调用了。二者在返回值的顺序上会有所差异。
我们来聊一聊里面的valueOf()和toString()方法。


5.6 toString()和valueOf()方法


1. {}.toString() 得到由"[object class ] "组成字符串
2. [].toString() 返回由数组内部元素以逗号拼接的字符串
3. xx.toString() 返回字符串字面量

- valueOf 也可以将对象转成原始类型
1. 包装类对象

屏幕截图 2024-05-21 144755.png


屏幕截图 2024-05-21 145140.png


5.6 == 比较


我们首先引入官方文档


image.png


首先我们看二者类型相同时的比较, 里面有一点需要注意,只要有一个NaN就返回false,其他的我们应该都清楚。


image.png


二者类型不相等时,我们需要特别注意的是,null和undefined是相等的,字符串和数字则把字符串转数字,布尔和其他把布尔转数字,出现对象先把对象转原始值。


估计上面的大量干货已经把大家快搞懵逼了,此这里我们做个简单小结,这里面的方法前面都有提到哦。


5.7 小结(重点)


对象转数字


Number(obj) => ToNumber(obj) => ToNumber(ToPrimitive(obj,Number))


对象转字符串


String(obj) => ToString(obj) => ToString(ToPrimitive(obj,String))


5.8 大量实战练习


屏幕截图 2024-05-21 145753.png


这一题我们知道+的作用和Number的方法是一样的。因此是转换为数字123.


屏幕截图 2024-05-21 150011.png


那么这一题,我们考虑到


Number([]) => ToNumber([]) => ToNumber(ToPrimitive([], Number))=> ToNumber('') => 0


屏幕截图 2024-05-21 150144.png


这里只要对象转布尔均为true


屏幕截图 2024-05-21 150534.png


这里的底层原理(5.3里说了)是,我们首先两边都调用ToPrimitive方法,看看有没有字符串,有的话就把另一方转换为字符串,没有的话就全部调用ToNumber方法相加。


屏幕截图 2024-05-21 150637.png


这里也是一样的原理。


屏幕截图 2024-05-21 151104.png


我们先把两边转换为原始值,左边为' ',右边为'[object object]',发现存在字符串,因此相加。


屏幕截图 2024-05-21 151257.png


这里只要我们看5.6就可以很轻松搞懂。


屏幕截图 2024-05-21 151406.png


同上一个。


屏幕截图 2024-05-21 151649.png


首先有对象,我们把对象转原始值,然后为NaN,为false.


屏幕截图 2024-05-21 152227.png


最后回到我们最开始的题目,首先碰见![],我们先把[]转为布尔,为true,!true为false,然后把左边对象转原始值,为' ' == false,出现布尔和字符串,把布尔转数字,为' ' == 0,出现字符串和数字,把字符串转数字,为0 == 0,因此最后结果为true


作者:落雪遥夏
来源:juejin.cn/post/7371312966364332042

0 个评论

要回复文章请先登录注册