• 作者:老汪软件技巧
  • 发表时间:2024-08-28 21:04
  • 浏览量:

引言

面试当中我们常会碰到一些奇奇怪怪的判断语句,隐藏在其中的类型转换可能会惹得许多小白困扰不已,接下来就由小编来讲清楚js中神鬼莫测的类型转换,拨开大家心底的迷雾。

首先来一段代码开开胃,说明打印结果的原因:

console.log(1 == '1');  // true
console.log(1 === '1');  // false
let a = []
let b = []
console.log([] == []);  // false

先要聊一聊‘==’和‘===’的区别:两个等号只判断两边变量的值是否相等,不在乎类型;三个等号要判断是否全等,值和类型都要相等。因为js引擎在用‘==’判断是否相等时会发生隐式类型转换,而‘===’判断时不会。

第6行打印false是因为js引擎在判断两边变量是否相等时只会读取里面的值,栈里变量a和b的值是中的两个不同的地址

显式类型转换原始值转原始值1. 原始值转布尔2. 原始值转数字

在字符串前放一个加号。这与调用Number构造函数效果相同是因为JS引擎在执行它们的时候都会自动调用一个ToNumber的函数,以此来将原始值转换为数值

console.log(+'123');  // 123

3. 原始值转字符串原始值转对象

console.log(new String(123)); // [String: '123']

隐式类型转换对象转原始值

对象转原始值我们通常只聊隐式的,因为日常开发中隐式转换的情况更常见,对比如 if判断语句中对象转布尔值:

let a = {}
if(a) {
    console.log('hello');
}

也可能是计算过程中对象与与原始值相加'1' + [1].....不论哪种,大多都不是开发者特地调用指定函数转换的,而是js引擎自动发生的。

转换方式:ToPrimitive()

ToPrimitive() 用于把对象转成原始类型,这种方法不是给我们开发者调用的,而是发生隐式类型转换时只有js引擎自己能用。它接收两个参数,第一个是要转换的对象,第二个是这个对象通过 ToPrimitive() 最终想转换成的类型。

如果obj接收到的是原始值,直接返回值如果接收到的是对象,调用toString,若得到原始值,直接返回否则,调用valueOf,若得到原始值,直接返回如果valueOf()返回的不是原始值,报错如果obj接收到的是原始值,直接返回值如果接收到的是对象,调用valueOf,若得到原始值,直接返回否则调用toString,若得到原始值,直接返回如果toString()返回的不是原始值,报错

ToPrimitive()转换至 String 类型或 Number 类型的过程区别就是调用 toString 方法和调用 valueOf 方法的先后顺序

toString()

toString方法有几个版本:

{}.toString() 得到由"[object" 和 class 和 "]" 组成的字符串[].toString() 数组的toString方法重写了对象上的toString方法,返回由数组内部元素以逗号拼接的字符串xx.toString() 返回字符串字面量,比如

let fn = function(){}; 
console.log( fn.toString() ) //  "function () {}"

valueOf()

也可以把对象转成原始值,但是仅限包装类对象

运算符的隐式转换规则一元运算符 +

前面提到原始值转成数值类型可以在字符串前添加一个加号,效果等同于Number(),即Number(str) == +str。同样,一个对象转换成数值也可以用一元运算符 +

js引擎自动调用ToNumber方法ToPrimitive([], Number)空字符串转成0二元操作符 +

v1 + v2 会发生的过程:

lprim = ToPrimitive(v1)rprim = ToPrimitive(v2)如果 lprim 和 rprim 其中有一个是字符串,那么另一个也要被转换为字符串,两者再拼接如果没有一个是字符串,ToNumber(lprim) + ToNumber(rprim)

举几个二元操作符 + 发生隐式类型转换过程的例子:

lprim = ToPrimitive(1) = 1,rprim = ToPrimitive('1') = '1'1 + '1'ToString(1) + '1''1' + '1' ===> '11'lprim = ToPrimitive(null) = 0 , rprim = ToPrimitive(1) = 10 + 1 ===> 1lprim = ToPrimitive([]) = '' , rprim = ToPrimitive({}) = '[object Object]''' + '[object Object]' ===> '[object Object]'==

等号两边值相等即为true,不同类型的变量在判断过程中js引擎会进行隐式类型转换

转换过程中需要注意的几点: (参考官方文档[Annotated ES5])()

举例: [] == ![]

取反优先级更高,[ ]转换成布尔得到true,再取反得到falsefalse转换成数值为 0[ ]转换成数值为空字符串空字符串转换成数值为00 == 0 ===> true结语

显式类型转换规则还是比较好记的,面试中大多偏向对隐式类型转换过程的考察,通常发生在比较运算符、算术运算符旁,我们需要理解并记忆ToPrimitive被调用的过程以及toString和valueOf方法的使用场景,牢记不同运算符的类型转换规则,每一步的转换都一定有对应的规则摆在那,只要符合规则,就一定能成功解答的。