JavaScript 数据类型隐式转换
面试题
在讲 JavaScript 的数据类型隐式转换前,我们先看道面试题:
1 | console.log(new String("abc") == true); |
结果是什么呢?
先把结果写下来,放在一边,然后继续看
字面量形式、包装器方式,new 方式的区别
创建字符串的三种方式:
1 | var a = "Davie"; //申明的是一个string类型,它是一个基本类型 |
使用 typeof 验证上面的结论
1 | var a = "Davie"; |
JavaScript 的数据类型
JavaScript 的数据类型之前已经讲过了,忘记的小伙伴出门左转,查看搞懂 JavaScript 的数据类型
4. 各种类型隐式转换到布尔类型对照表
数据类型 | 转换为 true 的值 | 转换为 false 的值 |
---|---|---|
Boolean | true | false |
String | 任何非空字符串 | “” 空字符串 |
Number | 任何非零数字 | 0 和 NaN |
Object | 任何对象 | null |
Undefined | 不适用 | undefined |
!
转换规则
!
会将后面的数据先转成布尔值,然后取反。例如:
1 | var a; |
==
比较
比较操作符会为两个不同类型的操作数转换类型,然后进行严格比较。当两个操作数都是对象时,JavaScript 会比较其内部引用,当且仅当他们的引用指向内存中的相同对象(区域)时才相等,即他们在栈内存中的引用地址相同。 —- 引用自 MDN
1. 类型相同的情况
- 如果比较的是两个对象,则比较两个对象的指针是否指向同一个对象,例如:
1 | var a = {} |
很明显,a
和b
在堆内存中是两个对象。二另一种情况:
1 | var a = {} |
这时,a
和b
就指向了同一个对象,所以相等。
- 其它的基本类型,如果是相同类型,则直接进行严格比较就好,没什么好说的。
2. 类型不同的情况
如果两边类型不同,则两边都尝试转成 number 类型。对于引用类型,先调用valueOf()
,如果能转成数字,则进行比较。不能转成数字就调用toString()
方法转成字符串。
1 | var a = "123"; |
如果有一边是 object 类型:
1 | var a = new String(123); |
再看一个:
1 | var a = {} console.log(a == 1) |
3. null、NaN、undefined
null、NaN、undefined 和 string、number、boolean、object 类型比较时,都不做隐式转换,比较的结果直接为 false。但是需要注意以下几个规则:
1 | console.log(NaN == NaN); //false |
4. 面试题解析
搞清楚规则后,开头的面试题就很容易了:
第一题:
1 | //问题1: |
第二题:
1 | //问题2: |
第三题:
1 | //问题3: |
5. 总结
- 类型相同
- 基本类型,直接比较值
- 引用类型比较指针
- 类型不同,尝试转成 number 类型,
- 先调用
valueOf()
转成number
- 不行就再用
toString()
方法转成string
- 先调用
- null、NaN、undefined 单独一套规则
比较运算符 >
<
来,在来看一道题:
1 | console.log('666' < '7') |
正确答案是 true
这是因为字符串类型比较大小时,不进行类型转换,而是逐位比较 ascii 码,第 1 位不同则返回结果,否则继续比较第 2 位,直到某一位不同为止。
在比如使用数组的 sort 方法排序:
1 | var a = [1, 10, 6, 100].sort(); |
结果是:
1 | [1, 10, 100, 6]; |
原因是 sort()方法默认的比较规则会先把每个元素转成字符串,然后比较字符串的 ascii 码来确定先后顺序。
加号+
+
运算符即可以对两个数相加,也可以连接字符串,那如果是[1,2,3]+4 这种情况下又会发生什么呢?这就需要我们了解相应的规则,为了方便描述,我们把+号左侧的值叫做 A,右侧的叫做 B:
第一步:如果 A 和 B 都是 number 类型,直接相加;
第二步:接下来看 A 或 B 中是否有一个是否为 string 类型,如果有,则将另一个也转成字符串,然后连接;
第三步:既不是 number,也不是 string,则按如下规则转换:
- 能转换成数字,返回之
- 否则调用 valueOf(),如果执行结果是基本类型,返回之;
- 否则调用 toString(),如果执行结果是基础类型,返回之;
- 无法得到原始值,抛异常。
减号-
除了加号外,减号也很神奇。
使用减号在做非数字类型的运算时,也会发生隐式类型转换.来看下面几个例子:
- true 会转换成 1
1 | 5 - true; // 4 |
- ‘’空字符串、null 转成 0
1 | 5 - '' //55 - null //5 |
- undefined 和非空字符串转成 NaN
1 | 5 - undefined // NaN5 - 'a' // NaN |
- 可以转成数字的字符串转成数字
1 | 5 - '1' //4 |