类型转换,听我讲讲 []==![] 返回true 这个事

类型转换,听我讲讲 []==![] 返回true 这个事

技术博客 admin 518 浏览

类型转换

前言

在JavaScript这门语言的编程世界里,数据类型之间的转换让代码能够灵活地处理各种场景。从原始值转原始值,原始值转对象,和对象转原始值,JavaScript提供了多种转换方式,既有显式的也有隐式的。这些转换机制不仅让编程变得更加灵活,也带来了一些需要注意的陷阱和挑战。本文将带领读者从JavaScript的底层机制出发,结合官方文档,细致入微地剖析其类型转换机制。

原始值转化为XXX

JavaScript中的原始类型包括数字、字符串、布尔值、null和undefined。原始值之间可以进行相互转换,同样原始值也可以通过其对应的包装对象(如NumberStringBoolean)来转换为对象。下面是原始值转化为xxx的表格示例。

原始类型 原始值 转换为布尔值 转换为数字 转换为字符串 转换为对象
数字 0 false 0 "0" new Number(0)
数字 10 true 10 "10" new Number(10)
数字 -5 true -5 "-5" new Number(-5)
字符串 "" false 0 "" new String("")
字符串 "Hello" true NaN "Hello" new String("Hello")
字符串 "false" true NaN "false" new String("false")
undefined undefined false NaN "undefined" N/A
null null false 0 "null" N/A
NaN NaN false NaN "NaN" N/A
布尔值 true true 1 "true" new Boolean(true)
布尔值 false false 0 "false" new Boolean(false)

对象转原始值(重点)

在 JavaScript 中,当需要将对象转换为原始值时,V8引擎会调用对象的 ToPrimitive() 方法来实现这一转换过程。

ToPrimitive()

ToPrimitive() 方法的主要作用是将对象转换为原始值。它接受一个参数,即表示期望的转换结果类型,可以是字符串或者数字。具体来说,ToPrimitive() 方法内部会检查对象是否实现了 Symbol.toPrimitive 方法,如果有,就调用该方法进行转换;否则,根据期望的结果类型,依次尝试调用对象的 valueOf()toString() 方法,直到得到原始值为止。

这是官方文档说明:

下面小编通过简略的语言总结了一下ToPrimitive() 将对象转换为原始值的步骤:

  1. 如果接收到的是原始值,不操作直接返回值

  2. 否则,调用toString方法,如果得到原始值返回

  3. 否则,调用valueOf方法,如果得到原始值返回

  4. 否则,报错

下面对toString()方法和valueOf()方法进行详解!注意如果是想把对象转化为数字则会先执行valueOf方法,反之,如果是想把对象转化为字符串则会先执行toString方法!

toString()方法

toString()方法规则:

  • {}.toString() 得到'[object Object]'

  • [].toString() 得到由数组内部元素以逗号拼接的字符串

  • xx.toString() 得到字符串字面量

valueOf()方法

valueOf()方法规则:

  • 仅限于包装类对象

对象转布尔,一定是true

对象转换为布尔值时会被视为 true,这意味着对象在逻辑运算中会被当作真值。

显示转换

显式类型转换是通过一些内置函数或操作符来明确地将一个数据类型转换为另一个数据类型,常见的显式类型转换方法包括:(均遵循上述原始值转原始值的规则)

  • parseInt():将字符串转换为整数。

  • parseFloat() :将字符串转换为浮点数。

  • Number():将值转换为数字。

  • String():将值转换为字符串。

  • Boolean():将值转换为布尔值。

隐式转换

在JavaScript中,当不同类型的值相互操作时,会发生隐式类型转换。例如,当字符串和数字相加时,JavaScript会将数字转换为字符串以进行连接。隐式类型转换的场景包括算术运算、比较运算以及逻辑运算等。下面对针对一些主要的隐式转化运算进行解释!

一元运算符+

一元运算符 + 可以用于将值转换为数字类型!

对于原始类型遵循上述原始值转数字的规则

对于对象,我们来通过一个示例深入解析一下

js
复制代码
let result = +{}; // 结果是 NaN console.log(result);

当应用一元加法操作符 + 到一个空对象 {} 时,JavaScript 首先会尝试调用对象的 valueOf 方法来获得一个原始值,但是valueOf 方法无法将{}转化为原始值。因此 JavaScript 将尝试调用对象的 toString 方法来获取字符串形式的值,然后再尝试将其转换为数字。

空对象的 toString方法返回的是 "[object Object]",这是对象的默认字符串表示形式。然后,JavaScript 尝试将 "[object Object]" 转换为数字,但由于该字符串不能被直接转换为数字,因此最终结果将是 NaN(Not a Number)。

二元运算符+

  1. 当执行表达式 v1 + v2 时,JavaScript 首先会尝试对 v1v2 进行 ToPrimitive 操作,将它们转换为原始值。

  2. ToPrimitive 操作会首先检查对象是否有 valueOf 方法。如果有并且返回的是原始值,则使用该值。否则,会继续检查是否有 toString 方法。如果存在 toString 方法并返回原始值,则使用该值。如果 valueOf 和 toString 都不存在或者都没有返回原始值,将会抛出 TypeError。

  3. 如果经过 ToPrimitive 操作后,v1v2 中有一个是字符串,则会将 v1v2 都转换为字符串(通过调用 toString 方法),然后进行字符串拼接。

js
复制代码
let v1 = 5; let v2 = "10"; let result1 = v1 + v2; // 结果是 "510",因为 v1 被转换为字符串然后和 v2 进行拼接 console.log(result1);
  1. 如果 v1 和 v2 都不是字符串,则会将它们分别转换为数字(通过调用 ToNumber 方法),然后进行数值相加。
js
复制代码
let v3 = 5; let v4 = true; let result2 = v3 + v4; // 结果是 6,因为 true 被转换为数字 1,然后和 v3 相加 console.log(result2);

==

这是官方文档中关于 == 的讲解:

我把 == 的规则总结如以下表格:

x y 比较结果
Undefined Undefined true
Null Null true
Number NaN false
+0 -0 true
-0 +0 true
String String true/false (根据内容是否完全相同)
Boolean Boolean true/false (如果都是true或false)
同一对象 同一对象 true
null undefined true
undefined null true
Number String x == ToNumber(y)
String Number ToNumber(x) == y
Boolean / ToNumber(x) == y
/ Boolean x == ToNumber(y)
String/Number Object x == ToPrimitive(y)
Object String/Number ToPrimitive(x) == y

这里我们将可以介绍一下[] == ![]的原因了

  1. 首先,![] 运算符会将空数组 [] 转换为布尔值。在 JavaScript 中,空数组被视为一个真值,所以 ![] 的结果是 false

  2. 接下来,根据 JavaScript 的类型转换规则,当对比不同类型的值时,会尝试将它们转换为相同的类型。在进行 == 比较时,如果一个操作数是布尔值,另一个操作数不是布尔值,则会将布尔值转换为数字再进行比较。

  3. 对于 [] == false,JavaScript 将空数组 [] 转换为原始值。由于这里涉及到对象到原始值的转换,JavaScript 会调用对象的 valueOf 方法,然后是 toString 方法。但由于数组的 valueOf方法并不返回原始值,因此 JavaScript 将转而调用数组的 toString 方法。空数组的 toString 方法返回空字符串 ""

  4. 接着,JavaScript 将空数组 [] 转换为字符串后,再将字符串转换为数字。空字符串转换为数字时会得到 0

因此,最终 [] == ![] 这个表达式会被转换为 [] == false,然后空数组 [] 被转换为数字 0,而 false 被转换为数字也是 0,因此最终结果是 true

js
复制代码
console.log([] == ![]); // 输出 true

最后

通过上述讲解,小编对类型转换理解得更加深刻了,希望你也能有所收获!

源文:类型转换,听我讲讲 []==![] 返回true 这个事

如有侵权请联系站点删除!

技术合作服务热线,欢迎来电咨询!