前言
在JavaScript
的广阔天地里,类型转换是一个既基础又深奥的课题。它如同一位默默无闻的幕后工作者,悄然影响着代码的执行流程和结果。无论是初学者还是资深开发者,都难免会在与类型转换的交锋中遇到困惑和挑战。但正是这份复杂性,赋予了JavaScript
灵活而强大的表达能力。本文旨在深入剖析JavaScript
的类型转换机制,揭示其背后的原理和规则。通过理解和掌握这些类型转换的奥秘,我们将能够编写出更加准确、高效和健壮的代码,从而在JavaScript
的编程之路上迈出更加坚实的步伐。
==vs===
js 代码解读复制代码console.log('1'==1);
console.log('1'===1);
看一下这两行代码,猜一猜它的执行结果
可以看到这两个代码执行结果是不相等的
所以我们要知道===; 叫全等,不会进行隐式类型转换,意味着会判断值和类型是否相等,==;会进行隐式类型转换,所有只会判断值是否相等
类型转换
我们来看看下面这道大厂面试题
js 代码解读复制代码console.log([]==[]);
console.log([]==![]);
判断这两段代码的输出结果,第一个我们都知道引用类型比较的是地址值,而不存在两个地址值完全相等的对象,因此第一行代码输出的肯定是false
,那为什么加个!就相等了呢,我们都知道!在js
中只是一个相反符号,这能有什么作用呢,其中就涉及到了类型转换,而面试官想问的就是你对类型转换的理解。读完这篇文章,你就能对类型转换有一个很深的理解了
原始类型之间的转换
我们先来想一下什么样子的代码进行与原始类型之间的转换,比如刚刚那==就是,还有就是字符串和数字的相加
js 代码解读复制代码1 + '1'=='11'
像这行代码,它会先把数字1转换为字符串'1'
,然后再拿两个字符串相加,就得到了'11'
,
js 代码解读复制代码'1' + true = '1true'
那字符串加布尔类型呢,要知道相加肯定要先转换为同一类型,布尔和布尔肯定是不能相加的,那会都转换为数字吗,也不是,布尔类型会先转换为字符串,然后再和字符串相加
我们知道一共有七种原始类型(Number,String,Boolean,bigInt,undifined,Null,Symbol()
),而后面四种都不会有其它类型转为它们的情况,所以原始类型转换只有三种情况,转布尔,转字符串,转数字。
转布尔
js 代码解读复制代码console.log(Boolean(true));
console.log(Boolean(undefined));
console.log(Boolean(null));
console.log(Boolean(-100));
console.log(Boolean(0));
console.log(Boolean(NaN));
console.log(Boolean('hello'));
console.log(Boolean(''));
我们将各种类型转为布尔看看都会转换为什么
可以看到布尔转布尔就是相当于没转,而有效数字转为布尔都为true,0
为false,NaN
为false
,有字符的字符串转为布尔为true
,空字符串为false,null
和undefined
为false
。这些就是转为布尔的全部规则了
转数字
js 代码解读复制代码console.log(Number(1));
console.log(Number('0'));
console.log(Number(undefined));
console.log(Number(null));
console.log(Number('hello'));
我们看看其它类型转数字是怎么样的
如果传入的是一个数字,其实它是不会转换的,而是将数字直接输出,如果是数字字符串,那么就会转换为对应的数字,undefined
会转为NaN
,而null
会转换为0
,如果是一个字符串,那么就不知道转换为什么数字,于是就会转换为未知数字NaN
。
转字符串
原始类型转字符串是最简单粗暴的,就是用一对引号引起来。
对象转为原始值
对象转换为字符串
js 代码解读复制代码let a ={}
console.log(String(a));
我们将对象转换为字符串是怎么样的,看看输出结果
为什么是这样的呢,其实在将对象转换为字符串的时候,v8引擎会先调用ToString
方法,解决不了,然后就会使用ToPrimitive()
方法,然后使用对象的toString
方法转换为字符串。然后对象转字符串的方法在Object
上,这是toString()
方法执行的官方文档
这个文档表示的是当 Object.pritotype.toString.call()
被执行的时候会干的几步操作,如果是undefined
的话,那就直接返回[object Undefined]
,如果是null,那就返回[object Null]
。
其它的,设0为调用To0bject
的结果,将this
值作为参数传递ToObject(this)
设class
为0的[[Class]]
内部属性的值。[[Class]]
是js
内部的属性,只有v8能用,可以直接读取变量的类型,最后返回由“[object ”、class 和 “]
” 三块拼接的结果。
那为什么数组转为字符串是这样的,我们看了官方文档,如果是用的Object
上的toString
方法,格式就绝对不是这样的。那到底是为什么呢,其实是在数组的构造函数上重写了这个方法,而在数组上的toString
方法就会返回由数组中元素由逗号分隔的字符串。
除了对象和数组,其它引用类型用toString转换为字符串都是直接返回 xx 的字符串字面量。
对象转布尔
在官方文档上就一条,true,无论什么对象转为布尔都是true
对象转数字
方法Number(obj)
过程 :To Number({})
//ToPrimitive({})
转数字会调用To Number({})
,然后调用然后对象不能直接转为数字,就会使用ToPrimitive({})
,转为原始类型最后再通过原始类型转换又再次变为数字
ToPrimitive({})
ToPrimitive(obj,String)
-如果obj
是原始类型,直接返回
-否则调用toString()
方法,如果得到原始类型则返回
-否则调用valueOf()
方法,如果得到原始类型则返回
-否则报错
ToPrimitive(obj,Number)
-如果obj
是原始类型,直接返回
-否则调用valueOf()
方法,如果得到原始类型则返回
-否则调用toString()
方法,如果得到原始类型则返回
-否则报错
隐式类型转换场景
1.四则运算:+ - * / %
2.判断语句 if while == > < >= <= !=
一元运算符 +
转数字类型
二元运算符 +
val1 + val2
lprim = ToPrimitive(val1)
rprim = ToPrimitive(val2)
如果 lprim或者rprim是字符串,另一个值直接被ToString()
- 否则,都处理为数字,返回ToNumber(lprim) + ToNumber(rprim)应用加法运算的结果
==
如果类型相同,就比较值。 如果是null和undifined,那么返回true
其它的,如果是类型不同的比较,都是先转为数字再进行比较
最后我们再来看这道大厂面试题
js 代码解读复制代码console.log([]==[]);
console.log([]==![]);
为什么加个!就是true
了呢,我们来类型转换分析一下,首先由于前面加了一个!
,那么就会使[]转换为布尔类型,前面我们提到过,所有引用类型转为布尔类型都会转为true
,这是官方制定的规则,然后被!
变为false
,接下来就是两个不同类型用==
进行比较了,那么我们就要先把它们转换为数字再比较,false
转为数字就是0,而[]需要用toString
转换为字符串,也就会变成空字符串'',然后再将字符串转为数字,空字符串转为数字就是0
,最后v8就是将它们变成了0==0
,当然返回的就是ture
看懂这些,那么你就已经掌握了js
中类型转换这个知识点了。
结语
我们深入了解了JavaScript
中的类型转换机制,学习了如何将原始类型和对象转换为字符串、数字和布尔值,并掌握了在特定场景下的类型转换规则。这不仅有助于我们更好地理解JavaScript
的比较和运算行为,也为我们解决面试和实际开发中的类型转换问题提供了有力的武器。类型转换是JavaScript
中的一个重要且复杂的概念,但通过不断学习和实践,我们可以逐渐掌握它,从而写出更加健壮和可靠的代码。
评论记录:
回复评论: