JS:类型转换(四)从底层逻辑让你搞懂经典面试问题 [ ] == ![ ] ?

前言

JavaScript中类型转换是一个很令人头疼的问题,特别是对于初学者来说。这是由于 JavaScript 是一种弱类型语言,它在运行时会尝试自动转换数据类型,以使表达式能够执行。这种灵活性使得 JavaScript 非常强大,但也容易引发一些不直观的行为。就比如当字符串与数字相加时,例如"3" + 2,JavaScript 将数字 2 隐式转换为字符串,而不是执行数学运算。今天我们就来聊聊JS中的类型转换规则,并且带你解决经典面试问题[ ] == ![ ] ?。

在前面三篇文章中,我们详细的介绍了原始数据类型之间的互相转换,以及对象类型转原始数据类型,接下来我们来聊聊什么时候会用到类型转换以及这道面试题该怎么解

首先我们先来看两道例题,我们将对象转换为原始数据类型,运用我们上篇所讲知识,看看会输出什么:

js 复制代码
console.log(Number({}));  // NaN
console.log(Number([]));  // 0
    • 首先我们先来看看将空对象{}转化为Number型的,我们可以看到答案为NaN,我们来分析一下,我们在对对象进行类型转换时,JS引擎会进行两个操作,ToPrimitive({}, Number),第一步,我们先来看看{}是不是基本类型,很显然不是,它是一个对象数据类型;接下来,我们调用valueof方法,我们知道valueof只能将包装类转换为它们对应的原始值,{}也不是包装类,所以我们不能得到原始值。接下来我们进行第三步,调用toString方法,{}空对象调用toString方法得到'[object Object]',得到一个字符串类型的原始值。第一个操作结束

    • 接下来进行第二个操作,将得到的原始值转化为对应的Number类型的值,因为原始值为'[object Object]',所以转化为数字类型时得到NaN

    • 接下来我们来看看将空数组[]转化为Number型的,我们知道数组也是对象,这里得到的答案为0,首先引擎先进行第一个操作,ToPrimitive([], Number),第一步,我们先来看看[]是不是基本类型,很显然不是,它是一个对象数据类型;接下来,我们调用valueof方法,我们知道valueof只能将包装类转换为它们对应的原始值,[]也不是包装类,所以我们不能得到原始值。接下来我们进行第三步,调用toString方法,[]空数组调用toString方法得到'',空字符串是一个字符串的原始值。第一个操作结束

    • 我们进行第二个操作,将得到的原始值''转化为对应的Number类型的值,所以空字符串在转化后得到0

一元运算符 +

在JavaScript中,一元运算符+可以用于将值转换为数字类型。这个操作符会尝试将其后面的操作数转换为一个数字。我们来看几个例子:

js 复制代码
console.log(+'1') // 相当于Number('1')   输出 1

+号后面跟一个东西时,JS引擎会将它转换为Number类型,所以将字符串'1'转化为数字1, 所以输出1.

js 复制代码
console.log(+[])    // 0

这里就相当于我们上面所讲的,+[ ] 相当于 Number([]),先调用ToPrimitive([], Number),得到原始值'',最后得到0

js 复制代码
console.log(+ {})   // NaN

这里就相当于我们上面所讲的,+{} 相当于 Number({}),先调用ToPrimitive({}, Number){}空对象调用toString方法得到'[object Object]',得到一个字符串类型的原始值。接下来进行数字类型转换,得到NaN,所以最后输出NaN

js 复制代码
console.log(+ [1, 2, 3]) // NaN

console.log(+ [1, 2, 3])相当于Number(+ [1, 2, 3]),先调用ToPrimitive(obj, Number),因为不是包装类,调用valueof并不能得到原始值,所以调用toString方法,得到'1,2,3'字符串,然后将字符串转化为Number类型,最后得到NaN

二元运算符 +

lprim + rprim == Toprimitive(v1) + Toprimitive(v2)

1. 转换之后当+两边有一个是字符串, 则按字符串进行拼接

2. 否则, 转到 number 进行计算

Toprimitive(v1),v1为原始数据类型时,那么直接返回该值

例如:

js 复制代码
console.log(1 + '1');  // '11'

Toprimitive(v1) + Toprimitive(v2)之后,得到1 +'1',发现 +号两边有一边为字符串类型,那么则进行字符串拼接看i,先将1转为为字符串类型得到'1',最后拼接得到'11'

js 复制代码
console.log(1 + null);  // 1

Toprimitive(v1) + Toprimitive(v2)之后,得到1 + null,发现两边没有任何字符串,则转换到数字类型Number进行计算,将null转换为Number,得到0,所以最后输出 1 + 0 = 1

js 复制代码
console.log([] + []);  // ""

Toprimitive(v1) + Toprimitive(v2)之后,得到'' + '',发现两边都为字符串,则将两个空字符串进行拼接,最后得到''

js 复制代码
console.log([] + {});  // '[object Object]'

Toprimitive(v1) + Toprimitive(v2)之后,得到'' + '[object Object]',发现+号两边都为字符串,所以将它们两个进行拼接,最后得到'[object Object]'

经典面试题

[ ] == ![ ] ?

在JavaScript中,[ ] == ![ ] 表达式的结果是 true 让我们解释一下:

  1. [ ] 是一个数组,它被视为一个对象。当使用相等运算符(==)比较两个对象时,JavaScript 将尝试将它们转换为相同的类型。
  2. ![ ] 中的 ! 是逻辑非运算符,它将数组 [ ] 转换为布尔值并取其相反值。由于数组被视为一个真值,![ ] 将为 false
  3. 然后,比较 == 进行的是类型转换后的值。在比较对象时,JavaScript 会尝试将它们转换为原始值。对于数组,转换后的原始值是一个空字符串。

因此,实际上,表达式 [ ] == ![ ] 转化为 "" == false,之后会将它们转化为Number类型,也就是0 == 0,因此整个表达式的结果是 true

我们来看看伪代码:

js 复制代码
 [] == ![]     true

 [] == !true
 [] == false
 '' == 0
 0 == 0

总结

一元运算符+

在JavaScript中,一元运算符+可以用于将值转换为数字类型。这个操作符会尝试将其后面的操作数转换为一个数字。

二元运算符+

lprim + rprim == Toprimitive(v1) + Toprimitive(v2)

1. 转换之后当+两边有一个是字符串, 则按字符串进行拼接

2. 否则, 转到 number 进行计算

相关推荐
小二·21 小时前
Python Web 开发进阶实战:Flask 项目中的表单验证、错误处理与用户体验优化
前端·python·flask
天荒地老笑话么21 小时前
IntelliJ IDEA 运行 Tomcat 报错:Please, configure Web Facet first!
java·前端·tomcat·intellij-idea
王五周八21 小时前
html转化为base64编码的pdf文件
前端·pdf·html
神色自若21 小时前
vue3 带tabs的后台管理系统,切换tab标签后,共用界面带参数缓存界面状态
前端·vue3
мо仙堡杠把子ご灬21 小时前
微前端架构实践:避免Vuex模块重复注册的崩溃陷阱
前端
叫我:松哥21 小时前
基于机器学习的地震风险评估与可视化系统,采用Flask后端与Bootstrap前端,系统集成DBSCAN空间聚类算法与随机森林算法
前端·算法·机器学习·flask·bootstrap·echarts·聚类
赵民勇21 小时前
JavaScript中的Mixin模式详解
javascript·ecmascript
呆头鸭L21 小时前
用vue3+ts+elementPlus+vite搭建electron桌面端应用
前端·vue.js·electron
aPurpleBerry21 小时前
React Hooks(数据驱动、副作用、状态传递、状态派生)
前端·react.js·前端框架
码农丁丁21 小时前
谈谈面试的本质
面试·职场和发展·技术管理·ai时代的技术管理