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 进行计算

相关推荐
web打印社区3 小时前
使用React如何静默打印页面:完整的前端打印解决方案
前端·javascript·vue.js·react.js·pdf·1024程序员节
喜欢踢足球的老罗3 小时前
[特殊字符] PM2 入门实战:从 0 到线上托管 React SPA
前端·react.js·前端框架
小光学长3 小时前
基于Vue的课程达成度分析系统t84pzgwk(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
前端·数据库·vue.js
Baklib梅梅4 小时前
探码科技再获“专精特新”认定:Baklib引领AI内容管理新方向
前端·ruby on rails·前端框架·ruby
南方以南_4 小时前
Chrome开发者工具
前端·chrome
YiHanXii5 小时前
this 输出题
前端·javascript·1024程序员节
Dream it possible!5 小时前
LeetCode 面试经典 150_链表_合并两个有序链表(58_21_C++_简单)
leetcode·链表·面试·1024程序员节
楊无好5 小时前
React中ref
前端·react.js
维他命Coco5 小时前
js常见开发学习
javascript
程琬清君5 小时前
vue3 confirm倒计时
前端·1024程序员节