前言
很多人在被面试问道 []==![] 的输出结果时,经常会眼前一蒙,搞不懂输出结果和其中的原理,接下来小编将通过 官方文档 和 画图 的方式让大家理解JS类型转换的原理
类型转换的种类
类型转换分为显式转换和隐式转换两种
- 显式类型转换 程序员通过代码明确指定进行的类型转换,通常使用内置函数或操作符。
let x=1
let y=String(x)
- 隐式类型转换 JavaScript 引擎在运算过程中自动进行的类型转换,通常发生在操作符的使用过程中
let x=1
let y="1"
console.log(x==y)
类型转换的触发方法
常见的显式类型转换方法:
-
字符串转换:
String(value)value.toString()
let num = 123; let str1 = String(num); // "123" let str2 = num.toString(); // "123" -
数字转换:
Number(value)parseInt(string, radix)parseFloat(string)+value(一元加号操作符)~~value(双非操作符,仅适用于整数部分)
let str = "123"; let num1 = Number(str); // 123 let num2 = parseInt(str, 10); // 123 let num3 = +str; // 123 let num4 = ~~str; // 123(仅适用于整数部分) -
布尔转换:
Boolean(value)!value(然后取反)
let num = 0; let bool1 = Boolean(num); // false let bool2 = !num; // true (然后取反)
常见的隐式类型转换场景:
-
字符串拼接:
当使用加号 (+) 操作符时,如果其中一个操作数是字符串,另一个操作数会被转换成字符串,然后进行拼接。let num = 123; let str = num + "abc"; // "123abc" -
算术运算:
当使用减号 (-)、乘号 (*)、除号 (/)、取余 (%) 等算术操作符时,操作数会被转换成数字。let str = "42"; let result = str - 10; // 32 -
比较运算:
当使用比较操作符 (>,<,>=,<=,==,!=,===,!==) 时,JavaScript 会根据需要进行类型转换。==和!=会进行类型转换,比较的是转换后的值。===和!==不会进行类型转换,比较的是值和类型。
"42" == 42; // true (因为 "42" 被转换成数字 42) "42" === 42; // false (因为类型不同) -
逻辑运算:
当使用逻辑与 (&&)、逻辑或 (||) 时,操作数会被转换成布尔值。let result = "Hello" && 0; // 0 (因为 "Hello" 被转换成 true,然后 true && 0 = 0) let anotherResult = "" || "World"; // "World" (因为 "" 被转换成 false,然后 false ||
类型转换的机制
隐式类型转换的过程中,虽然程序员没有书写对应的转换方法,但是在 js 的执行引擎中还是默认使用了对应的构造函数:Boolen() Number() String()。类似于这样的操作
"42" == 42
Number("42") == 42
Boolen()
Boolen把值传给ToBoolenToBoole直接返回输出的值
Number()
-
Number把值传给ToNumber
-
如果值是原始类型,ToNumber直接传对应的值,如果值是引用类型,返回ToNumber(ToPrimitive(value,Number))的值
-
ToPrimitive(value,Number)执行下列操作
- 如果value是原始类型,直接返回
- 否则调用valueof(value),如果得到原始类型,直接返回给ToNumber
- 否则调用toString(value),如果得到原始类型,直接返回ToNumber
- 否则报错
意思为不能转化的字符串返回NAN(空字符串转0)
ToPrimitive
ToPrimitive(value, hint) 接收两个参数:
value:要转换的值,它可以是任何JavaScript值,但在这个上下文中,我们主要关心的是对象类型。hint:一个字符串,表示期望的转换类型,它可以是"number"或"string"。这个参数指示了转换的“首选”方向,但并不能保证转换结果一定是这个类型的原始值。
当 hint 为 "number" 时,JavaScript引擎会尝试将对象转换为一个数字。这通常是通过调用对象的 valueOf() 方法(如果它返回一个原始值的话),如果 valueOf() 返回一个对象或者没有定义,那么会尝试调用 toString() 方法,并将其结果转换为数字(如果可能的话)。
valueOf
对于内置的包装类(如 Number, String, Boolean),valueOf 方法返回它们所包装的基本类型的值。
toString
在JavaScript中,toString 是一个非常重要的方法,它属于 Object.prototype,这意味着JavaScript中的所有对象都继承了这个方法(除非它们自己显式地重写了 toString)。toString 方法的主要作用是将对象转换为一个字符串
- Object
- 返回一个字符串 "[object,class]" 。class是实体对象身上的[[class]],[[class]]是实体对象的一个值,和它的类型有关
- 内置对象
- 对于内置的包装类(如
Number,String,Boolean),toString方法被重写以返回它们所包装的基本类型的值的字符串表示。
String
- String把值传给ToString
- 如果值是原始类型,ToString直接传对应的值,如果是ToString(ToPrimitive(value,String))
- ToPrimitive(value,String)执行下列操作
- 如果value是原始类型,直接返回
- 否则调用toString(value),如果得到原始类型,直接返回给ToString
- 否则调用valueof(value),如果得到原始类型,直接返回给ToString
- 否则报错
==类型转换的机制
==的类型转换分为两种
- 原始类型与原始类型
- 布尔值转换:在比较之前,布尔值
true会被转换为1,false会被转换为0。 - 字符串类型转换: - 当数字与字符串进行比较时,字符串会被尝试转换为数字。如果字符串无法转换为有效的数字(例如,它包含非数字字符),则转换结果为
NaN。 null和undefined:这两个值在相等运算符的比较中被视为相等(即null == undefined的结果为true)。但是,它们与任何其他类型的值进行比较时,结果都为false(除非该值也被转换为null或undefined)。NaN:NaN与任何值(包括它本身)进行比较时,结果都为false。
- 布尔值转换:在比较之前,布尔值
// 数字与字符串比较
console.log(0 == ""); // true,因为""被转换为0
console.log(1 == "1"); // true,因为"1"被转换为1
console.log(2 == " 2 "); // true,因为" 2 "被转换为2(忽略前后空格)
console.log(3 == "abc"); // false,因为"abc"无法被转换为有效的数字(NaN)
// 布尔值与数字比较
console.log(true == 1); // true,因为true被转换为1
console.log(false == 0); // true,因为false被转换为0
// null和undefined比较
console.log(null == undefined); // true
console.log(null == 0); // false
console.log(undefined == 0); // false
// NaN比较
console.log(NaN == NaN); // false
- 原始类型与引用类型
- 当对象或数组与字符串进行比较时,对象或数组通常会被转换为字符串,然后再进行比较。
// 对象与原始类型值比较
console.log([] == 0); // true,因为空数组[]被转换为""(空字符串),然后再转换为0
console.log([1] == 1); // true,因为[1]被转换为"1"(字符串),然后再转换为1(数字)
console.log([1, 2] == 1); // false,[1, 2]被转换为"1,2"(字符串),无法转换为1(数字)
console.log({} == "[object Object]"); // false,对象的转换行为更复杂,通常不直接转换为字符串进行比较
- 引用类型和引用类型
- 也就是说,只有当两个对象指向同一个内存地址时,比较结果才会为
true。
- 也就是说,只有当两个对象指向同一个内存地址时,比较结果才会为
// 引用类型和应用类型比较
[]==[]; //false, 因为引用的对象不同
[]==![]
[]==![]为true的原因
- 引用类型转Boolen全部转为true
![]先转为布尔类型true- []==true,
[]在相等运算符中,隐式类型转换为了true
[]==[]
[]==[]为false的原因
- 因为
==运算符在比较两个数组时,不会比较它们的元素,而是比较它们的引用。
结语
相信你已经搞清楚了类型转换的机制,面试官问你也不会再害怕