面试官问我为什么 [] == ![] 为 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 对象转布尔
![面试官问我为什么 [] == ![] 为 true, 我表面冷静,实则内心慌的一批](https://static.blogweb.cn/article/c2a08b6eb65e4b2581e30f2b4ea032cc.webp)
首先我们来到这题,最后结果会被打印,说明对象在转换为布尔值的时候,不管什么对象,都是被转换为true。
5.2 + 一元运算符
![面试官问我为什么 [] == ![] 为 true, 我表面冷静,实则内心慌的一批](https://static.blogweb.cn/article/23d5f34733a544fcb1add5b7f960bfac.webp)
我们先来了解一下,一元运算符的作用。查阅js官方文档,我们可以知道就是调用ToNumber()得到结果。而ToNumber()就是调用Number方式所调用的内置函数,因此就是强制转换为数字。我们也可以理解为+和Number()的作用是一样的。
5.3 + 二元运算符
![面试官问我为什么 [] == ![] 为 true, 我表面冷静,实则内心慌的一批](https://static.blogweb.cn/article/4c3ed89b1e8949f3ba5c857b500ecea0.webp)
二元运算符调用ToPrimitive()方法(ToNumber中的,转换方式有差异)。
5.4 ToNumber()方法
![面试官问我为什么 [] == ![] 为 true, 我表面冷静,实则内心慌的一批](https://static.blogweb.cn/article/0aa7b0c1be5a409a915f6575eac1d452.webp)
那么这个方法具体执行过程是什么呢?我们可以看到,如果是基本数据类型转数字,我们之前已经聊到,因此不必多聊,而面对对象转数字的时候,我们会先调用ToPrimitive方法。
5.5 ToPrimitive()方法
![面试官问我为什么 [] == ![] 为 true, 我表面冷静,实则内心慌的一批](https://static.blogweb.cn/article/fc3ffc167609473db1e6b32fba0ecedd.webp)
关于这个方法,我们要看是被ToNumber还是Totring方法给调用了。二者在返回值的顺序上会有所差异。 我们来聊一聊里面的valueOf()和toString()方法。
5.6 toString()和valueOf()方法
1. {}.toString() 得到由"[object class ] "组成字符串
2. [].toString() 返回由数组内部元素以逗号拼接的字符串
3. xx.toString() 返回字符串字面量
- valueOf 也可以将对象转成原始类型
1. 包装类对象
![面试官问我为什么 [] == ![] 为 true, 我表面冷静,实则内心慌的一批](https://static.blogweb.cn/article/e107ca9831004b45af9771dd84dcb29e.webp)
![面试官问我为什么 [] == ![] 为 true, 我表面冷静,实则内心慌的一批](https://static.blogweb.cn/article/31e884e4cf5b4100b3f8fda1de629020.webp)
5.6 == 比较
我们首先引入官方文档
![面试官问我为什么 [] == ![] 为 true, 我表面冷静,实则内心慌的一批](https://static.blogweb.cn/article/28dc7e6ca11a42cd95ef11847f7f4cf4.webp)
首先我们看二者类型相同时的比较, 里面有一点需要注意,只要有一个NaN就返回false,其他的我们应该都清楚。
![面试官问我为什么 [] == ![] 为 true, 我表面冷静,实则内心慌的一批](https://static.blogweb.cn/article/3607421120714d618246edf8cdeb9ab5.webp)
二者类型不相等时,我们需要特别注意的是,null和undefined是相等的,字符串和数字则把字符串转数字,布尔和其他把布尔转数字,出现对象先把对象转原始值。
估计上面的大量干货已经把大家快搞懵逼了,此这里我们做个简单小结,这里面的方法前面都有提到哦。
5.7 小结(重点)
对象转数字
Number(obj) => ToNumber(obj) => ToNumber(ToPrimitive(obj,Number))
对象转字符串
String(obj) => ToString(obj) => ToString(ToPrimitive(obj,String))
5.8 大量实战练习
![面试官问我为什么 [] == ![] 为 true, 我表面冷静,实则内心慌的一批](https://static.blogweb.cn/article/512dc92c419e45628b0eb57f7d37fc1b.webp)
这一题我们知道+的作用和Number的方法是一样的。因此是转换为数字123.
![面试官问我为什么 [] == ![] 为 true, 我表面冷静,实则内心慌的一批](https://static.blogweb.cn/article/40df1c452f8945c29a92527b9fa41bbc.webp)
那么这一题,我们考虑到
Number([]) => ToNumber([]) => ToNumber(ToPrimitive([], Number))=> ToNumber('') => 0
![面试官问我为什么 [] == ![] 为 true, 我表面冷静,实则内心慌的一批](https://static.blogweb.cn/article/8b3562cf3ba94e2c9647301a46527981.webp)
这里只要对象转布尔均为true
![面试官问我为什么 [] == ![] 为 true, 我表面冷静,实则内心慌的一批](https://static.blogweb.cn/article/98a560ad14f448459b84f7427b68e188.webp)
这里的底层原理(5.3里说了)是,我们首先两边都调用ToPrimitive方法,看看有没有字符串,有的话就把另一方转换为字符串,没有的话就全部调用ToNumber方法相加。
![面试官问我为什么 [] == ![] 为 true, 我表面冷静,实则内心慌的一批](https://static.blogweb.cn/article/2577b5c579c744dea2ee38091bb9225f.webp)
这里也是一样的原理。
![面试官问我为什么 [] == ![] 为 true, 我表面冷静,实则内心慌的一批](https://static.blogweb.cn/article/d1043ee4fedd48838070d73cc307d39d.webp)
我们先把两边转换为原始值,左边为' ',右边为'[object object]',发现存在字符串,因此相加。
![面试官问我为什么 [] == ![] 为 true, 我表面冷静,实则内心慌的一批](https://static.blogweb.cn/article/d4ec39bb9ab049f282631495e836dc45.webp)
这里只要我们看5.6就可以很轻松搞懂。
![面试官问我为什么 [] == ![] 为 true, 我表面冷静,实则内心慌的一批](https://static.blogweb.cn/article/5e558a42317442d0b28d28166dcff628.webp)
同上一个。
![面试官问我为什么 [] == ![] 为 true, 我表面冷静,实则内心慌的一批](https://static.blogweb.cn/article/aca0835125614afaa8fe55b97e6d6e4f.webp)
首先有对象,我们把对象转原始值,然后为NaN,为false.
![面试官问我为什么 [] == ![] 为 true, 我表面冷静,实则内心慌的一批](https://static.blogweb.cn/article/86d10e6bfd6b4a1b86c5de7df3595f29.webp)
最后回到我们最开始的题目,首先碰见![],我们先把[]转为布尔,为true,!true为false,然后把左边对象转原始值,为' ' == false,出现布尔和字符串,把布尔转数字,为' ' == 0,出现字符串和数字,把字符串转数字,为0 == 0,因此最后结果为true
转载自:https://juejin.cn/post/7371312966364332042