数据类型与类型转换
题目1: JavaScript中有哪些基本数据类型?
答案: JavaScript中的基本数据类型包括:undefined
、null
、boolean
、number
、string
、symbol
(ES6引入)和bigint
(ES11引入)。
扩展: 除了基本数据类型,JavaScript还有一种复杂数据类型:object
。object
包括对象、数组、函数等。基本数据类型存储的是值,而复杂数据类型存储的是引用地址。
题目2: ==
和===
的区别是什么?
答案: ==
进行的是类型转换的比较,===
进行的是严格比较,不会进行类型转换。使用===
可以避免隐式类型转换带来的问题,推荐使用。
扩展: ==
会在比较前尝试进行类型转换,比如数字与字符串进行比较时会将字符串转换为数字。例如:1 == '1'
返回true
,而1 === '1'
返回false
。
题目3: 如何检测一个变量的类型?typeof
、instanceof
和Object.prototype.toString.call()
的区别?
答案:
typeof
操作符可以检测基本数据类型(除了null
)和函数。instanceof
用于检测对象是否为某个构造函数的实例。Object.prototype.toString.call()
可以精确地检测任何类型。
扩展:
typeof null
返回"object"
,这是JavaScript的一个历史遗留bug。instanceof
不能跨框架(iframe)使用,因为每个框架都有自己的执行环境。Object.prototype.toString.call()
返回形如"[object Type]"
的字符串,其中Type
是对象的实际类型。
题目4: 什么时候会发生隐式类型转换?如何避免?
答案: 隐式类型转换主要发生在以下情况:
- 使用
==
进行比较 - 使用
+
运算符时,如果有一个操作数是字符串 - 逻辑运算符(
&&
、||
、!
) - 条件语句中的条件表达式
避免隐式类型转换的方法:
- 使用
===
和!==
进行比较 - 在进行运算前,显式地将变量转换为期望的类型
- 使用类型检查函数(如
typeof
)来确保类型正确
扩展: 隐式类型转换可能导致意外的结果,例如:[] + {}
返回"[object Object]"
,而{} + []
返回0
。这是因为JavaScript引擎对这两种表达式的解析方式不同。
题目5: NaN
是什么?如何检测一个值是否为NaN
?
答案: NaN
表示"Not a Number"(不是一个数字),它是一个特殊的数值,用于表示某个值不是合法的数字。检测一个值是否为NaN
的最可靠方法是使用Number.isNaN()
函数。
扩展:
NaN
不等于任何值,包括它自己。因此,NaN === NaN
返回false
。typeof NaN
返回"number"
,这可能会让人感到困惑。- 早期的
isNaN()
函数存在问题,它会将非数字值(如字符串)也判断为NaN
。ES6引入的Number.isNaN()
修复了这个问题。
题目6: JavaScript中的数字精度问题是如何产生的?如何处理?
答案: JavaScript使用IEEE 754标准的双精度浮点数来表示数字,这会导致某些小数无法精确表示,比如0.1 + 0.2 !== 0.3
。
处理方法:
- 对于金融计算,可以将小数转换为整数进行计算,然后再除以相应的倍数。
- 使用专门的库,如
decimal.js
或big.js
。 - 使用
Number.EPSILON
进行近似相等比较。
扩展: Number.EPSILON
是JavaScript能够表示的最小精度。对于比较小数是否相等,可以使用如下函数:
function areEqual(a, b) {
return Math.abs(a - b) < Number.EPSILON;
}
题目7: 解释一下JavaScript中的装箱和拆箱操作。
答案:
- 装箱(Boxing):将基本数据类型转换为对应的引用类型的操作。例如,将
number
类型转换为Number
对象。 - 拆箱(Unboxing):将引用类型转换为对应的基本数据类型的操作。
扩展:
- 装箱操作通常是隐式的,例如调用基本类型的方法时(如
"hello".toUpperCase()
)。 - 拆箱操作通常通过
valueOf()
或toString()
方法实现。 - 过度使用装箱和拆箱操作可能会影响性能,特别是在循环中。
题目8: 什么是类型强制转换?请举例说明。
答案: 类型强制转换是指将一种数据类型的值转换为另一种数据类型的值。JavaScript中的强制类型转换主要有以下几种:
- 转换为字符串:使用
String()
函数或者toString()
方法 - 转换为数字:使用
Number()
函数、一元加操作符(+
)或parseInt()
/parseFloat()
函数 - 转换为布尔值:使用
Boolean()
函数或者!!
操作符
扩展:
String(123); // "123"
(123).toString(); // "123"
Number("123"); // 123
+"123"; // 123
parseInt("123"); // 123
Boolean(1); // true
!!1; // true
题目9: Object.is()
与===
有什么区别?
答案: Object.is()
和===
大多数情况下的行为是相同的,但有两个特殊情况:
Object.is(NaN, NaN)
返回true
,而NaN === NaN
返回false
Object.is(+0, -0)
返回false
,而+0 === -0
返回true
扩展: Object.is()
是ES6引入的新方法,用于解决===
在处理NaN
和正负零时的一些特殊情况。在大多数情况下,使用===
就足够了,但如果需要区分+0
和-0
,或者需要将NaN
视为相等,那么Object.is()
会更合适。
题目10: 解释一下JavaScript中的真值(truthy)和假值(falsy)。
答案: 在JavaScript中,当一个值在布尔上下文中被评估时,它会被强制转换为布尔值true
或false
。
假值(Falsy)包括:
false
0
''
(空字符串)null
undefined
NaN
除了这些假值,其他所有值都是真值(Truthy)。
扩展:
- 空数组(
[]
)和空对象({}
)都是真值,这可能会导致一些意外情况。 - 在条件语句中,JavaScript会自动进行布尔转换,例如:javascript
if ([]) { console.log("This will be executed!"); }
- 使用双重否定(
!!
)可以将任何值显式转换为其对应的布尔值:javascript!![] // true !!0 // false