为什么 [] == ![] 为 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。

5.2 + 一元运算符

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

5.3 + 二元运算符

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

5.4 ToNumber()方法

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

5.5 ToPrimitive()方法

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

5.6 toString()和valueOf()方法

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

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

 

5.6 == 比较

我们首先引入官方文档

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

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

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

5.7 小结(重点)

对象转数字

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

对象转字符串

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

5.8 大量实战练习

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

那么这一题,我们考虑到

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

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

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

 这里也是一样的原理。

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

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

 同上一个。

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

 

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

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 

posted @ 2024-07-02 17:47  林恒  阅读(103)  评论(0编辑  收藏  举报