JavaScript 有时会有些“出人意料”,即便是看似简单的问题也可能暗藏玄机。以下是七个涵盖不同 JavaScript 特性的经典问题。它们看起来很简单,但往往会让人意外!如果你能答对这些问题,说明你对 JavaScript 的掌握已经很扎实了。
问题 1:0.1 + 0.2 === 0.3 的结果是什么?
console.log(0.1 + 0.2 === 0.3);
答案: false
解析:JavaScript 中,浮点数(带小数点的数字)在计算时并不总是精确的。例如,0.1 + 0.2 的结果并不是严格意义上的 0.3,而是 0.30000000000000004。这是由于计算机采用二进制来近似表示十进制浮点数所导致的误差。所以,0.1 + 0.2 === 0.3 的结果是 false。
问题 2:"5" + 3 和 "5" - 3 的结果是什么?
console.log("5" + 3);
console.log("5" - 3);
答案:"5" + 3 的结果是 "53""5" - 3 的结果是 2
解析:
- **"5" + 3**:当使用 + 操作符时,如果其中一个操作数是字符串,JavaScript 会将另一个操作数也转换为字符串,并将它们拼接在一起,因此结果是 "53"。
- **"5" - 3**:- 操作符不会作用于字符串。JavaScript 会将 "5" 转换为数字 5,然后进行数学运算,结果是 2。
问题 3:typeof null 的值是什么?
console.log(typeof null);
答案: "object"
解析:这是 JavaScript 中一个令人困惑的点。按理说,typeof 应该返回值的类型。然而,typeof null 返回 "object",这是历史遗留的一个设计问题。实际上,null 是一个特殊的原始类型值,表示“空”或“无值”。不过,为了兼容旧代码,这个问题一直没有修复。
问题 4:闭包是如何工作的?
function outerFunction() {
let count = 0;
return function () {
count++;
console.log(count);
};
}
const closure = outerFunction();
closure(); // ?
closure(); // ?
答案:输出为:
1
2
解析:闭包指的是函数能够记住它定义时所在的作用域环境,即使这个函数在别的作用域中执行。在这个例子中,outerFunction 返回了一个内部函数,该函数仍然可以访问 outerFunction 内部的 count 变量。每次调用 closure,count 都会递增,并打印其最新值。
问题 5:true + false 和 [] + {} 的结果是什么?
console.log(true + false);
console.log([] + {});
答案:true + false 的结果是 1[] + {} 的结果是 "[object Object]"
解析:
- **true + false**:在 JavaScript 中,布尔值会被转换为数字:true 是 1,false 是 0。因此,1 + 0 的结果是 1。
- **[] + {}**:加号用于非数字时,会触发类型转换。空数组 [] 转换为空字符串 "",空对象 {} 转换为字符串 "[object Object]",所以最终结果是 "[object Object]"。
问题 6:[] == ![] 的结果是什么?
console.log([] == ![]);
答案: true
解析:这背后包含了一些隐式类型转换:
- ![] 表示“非空数组”。由于空数组是“真值”(truthy),![] 变成了 false。
- 表达式变成了 [] == false。
- 比较时,JavaScript 会将 false 转换为数字 0,然后将 [] 转换为空字符串 ""。
- 最终,"" == 0 为 true。
问题 7:以下代码中 console.log(a) 的输出是什么?
console.log(a);
var a = 5;
答案: undefined
解析:这是 JavaScript 中的变量提升(hoisting)机制。在执行代码之前,JavaScript 会将变量声明提升到当前作用域的顶部。所以上述代码相当于:
var a;
console.log(a);
a = 5;
在 console.log(a) 执行时,a 已经声明但尚未赋值,因此输出 undefined。
总结
这些问题既展现了 JavaScript 一些奇特的行为,也涵盖了闭包、类型转换、变量提升等核心概念。理解这些内容不仅能避免常见的坑,还能提升对 JavaScript 的掌控能力。