题目1:加号 + 与减号 - 的类型隐式转换
‘5’ + 3; ‘5’ - 3; 的正确输出是什么?
// 选项:
// A. “53”, 2
// B. 8, 2
// C. error
// D. other
答案与分析:答案是 A。
对于表达式 ‘5’ + 2,其结果为 “52”。这是因为在 + 运算符中,只要有一个操作数是字符串,就会触发字符串连接操作,这是JavaScript基础语法中的常见规则。
关键在于,- 运算符的行为与 + 不同。它要求两个操作数都是数字。如果操作数不是数字类型,引擎会将其强制转换为数字,再进行减法运算。因此,‘5’ - 3 实际上执行的是 5 - 3,最终结果为 2。
题目2:过度使用正负号的表达式
1 + - + + + - + 1 的运算结果是多少?
// 选项:
// A. 2
// B. 1
// C. error
// D. other
答案与分析:答案是 A。
这种写法通常只出现在示例或挑战题中,在实际生产代码中应极力避免。理解它的关键在于两点:
- 一元正号
+ 会将操作数转换为数字(例如 +1 结果为 1)。
- 一元负号
- 在转换数字的同时会取负值(例如 -1 结果为 -1)。
我们可以通过在连续的符号之间插入 0 来帮助理解:1 + 0 - 0 + 0 + 0 + 0 - 0 + 1。经过正负号抵消后,最终等效于 1 + 1,因此结果为 2。了解这个原理即可,切勿在实际项目中编写此类难以维护的代码,这也是构建清晰可读的前端工程化代码的原则之一。
题目3:稀疏数组与 map 方法的陷阱
请分析以下代码的输出:
var ary = Array(3);
ary[0] = 2;
ary.map(function(elem) {
return “1”;
});
// 选项:
// A. [2, 1, 1]
// B. [“1”, “1”, “1”]
// C. [2, “1”, “1”]
// D. other
答案与分析:答案是 D。
实际运行结果是 [“1”, empty × 2](在控制台的显示可能略有差异)。这与Array.map的规范定义有关:map 方法会为数组中每个已赋值的索引按顺序调用一次回调函数,并将返回值组成新数组。回调函数不会为那些从未被赋值或已被 delete 删除的“空槽”调用。
在本题中,Array(3) 创建了一个长度为3但没有任何元素的稀疏数组。只有索引 0 被赋值为 2,因此 map 回调只会在索引 0 上执行一次,返回 “1”。索引 1 和 2 位置保持“空槽”状态,在新数组中体现为 undefined 或 empty。这属于JavaScript中数组方法的高级应用特性。
题目4:函数参数与 arguments 对象的双向绑定
请分析以下涉及JavaScript函数内部机制的代码输出:
function sidEffecting(ary) {
ary[0] = ary[2];
}
function bar(a, b, c) {
c = 10;
sidEffecting(arguments);
return a + b + c;
}
bar(1, 1, 1);
// 选项:
// A. 3
// B. 12
// C. error
// D. other
答案与分析:答案是 D。
实际运行结果是 21。这揭示了JavaScript中一个重要的历史特性:在非严格模式下,命名参数(a, b, c)与 arguments 对象之间存在双向绑定关系。
执行流程如下:
- 调用
bar(1, 1, 1),初始时 a = 1, b = 1, c = 1,arguments 为 [1, 1, 1]。
- 执行
c = 10,这同时更新了局部变量 c 以及 arguments[2] 的值。此时 arguments 变为 [1, 1, 10]。
- 调用
sidEffecting(arguments),将 arguments 对象传入。函数内执行 ary[0] = ary[2],即 arguments[0] = arguments[2],将 10 赋值给 arguments[0]。
- 由于双向绑定,
arguments[0] 的改变立刻同步到了命名参数 a。此时 a 的值也变成了 10。
- 最终计算
return a + b + c,即 10 + 1 + 10,结果为 21。
注意:在严格模式下(‘use strict’),这种双向绑定行为将被移除,参数变量与 arguments 对象完全独立,此题结果将变为 12。这属于JavaScript核心的网络/系统编程知识。
题目5:大整数运算与IEEE 754精度丢失
请分析以下大整数相加的结果:
var a = 111111111111111110000;
var b = 1111;
console.log(a + b);
// 选项:
// A. 111111111111111111111
// B. 111111111111111110000
// C. NaN
// D. Infinity
答案与分析:答案是 B。
这个现象并非JavaScript独有的缺陷,而是由于遵循 IEEE 754 双精度浮点数标准所导致的问题。在有限的64位存储空间内,当数值超过一定范围(具体是安全整数范围 (-2^53, 2^53))时,将无法精确表示每一个整数,发生精度丢失。
在本题中,变量 a 的数值已经超出了 JavaScript 能精确表示的整数范围。加上一个相对极小的数 b,无法改变 a 在内存中已被近似表示的值。因此,a + b 的结果在精度上仍等于 a 本身。
这是所有使用IEEE 754标准的语言都可能遇到的底层算法/数据结构精度问题,在处理财务、高精度计算等场景时需要特别注意。