JavaScript棘手代码第一部分
JavaScript代码系列(5部分)
JavaScript棘手代码第一部分
在JavaScript中处理设备方向
JavaScript棘手代码第二部分
JavaScript棘手代码第三部分
数组变异和非变异方法
问题1:这段JavaScript代码的输出是什么?
- var a = 10;
- function example() {
- console.log(a);
- var a = 20;
- }
- example();
输出: undefined
解释:
这段代码演示了JavaScript中一个常见的行为,称为变量提升。在JavaScript中,变量声明会被提升到其作用域的顶部,但赋值操作仍然保持在原位置。
当调用example()函数时,它首先尝试打印a的值。在函数内部,有一个var a = 20;语句,它在函数作用域内创建了一个新的局部变量a。然而,由于提升,var a;的声明被提升到函数的顶部,实际上使函数等同于:
- function example() {
- var a; // 提升的声明
- console.log(a); // 输出 undefined
- a = 20; // 赋值保持在原位置
- }
问题2:输出是什么?
- function trickyExample() {
- console.log(a);
- if (true) {
- var a = 10;
- }
- console.log(a);
- }
- trickyExample();
输出:
第一个console.log:undefined
第二个console.log:10
解释:
在trickyExample()函数中,if块前后都有一个console.log(a)语句。在块内部,有一个var a = 10;声明。由于变量提升,var a;声明被提升到函数作用域的顶部,使其在整个函数中都可以访问。
然而,在JavaScript中,在块内用var声明的变量不是块作用域的;它们是函数作用域的。这意味着在if块内声明的变量a在整个trickyExample()函数中都可以访问,甚至在if块之前也可以。
当调用trickyExample()时,第一个console.log(a)语句将输出undefined,因为a被提升但还没有被赋值。第二个console.log(a)语句将输出10,因为a已经在if块内被赋值为10。
问题3:输出是什么?
- function trickyFunction() {
- if (true) {
- var a = 5;
- let b = 10;
- }
- console.log(a);
- console.log(b);
- }
- trickyFunction();
输出:
第一个console.log:5
第二个console.log:ReferenceError
解释:
这个问题探讨了在JavaScript中块内用var和let声明的变量之间的差异。
在trickyFunction()中,有一个if块包含var a = 5;和let b = 10;声明。用var声明的变量是函数作用域的,并被提升到函数的顶部,而用let声明的变量是块作用域的,不会被提升。
当调用trickyFunction()时,var a被提升到函数的顶部,在整个函数中都可以访问。然而,let b是块作用域的,只在if块内可以访问。
第一个console.log(a)语句将输出5,因为var a由于提升而在整个trickyFunction()函数中都可以访问。
第二个console.log(b)语句将导致ReferenceError,因为let b被块作用域限制在if块内,在块外无法访问。
问题4:输出是什么?
- var variable = 10;
- (() => {
- console.log(variable);
- var variable = 20;
- console.log(variable);
- })();
输出:
第一个console.log:undefined
第二个console.log:20
解释:
在给定代码中,变量variable被声明并赋值为10。在立即调用函数表达式(IIFE)内部,同一个变量被用var重新声明并赋值为20。由于提升,第一个console.log(variable)打印undefined(变量被声明但还没有被赋值),第二个console.log(variable)打印20。这演示了JavaScript中提升和变量重新声明的影响。
问题5:输出是什么?
- var a = 1;
- function b() {
- a = 10;
- return;
- function a() {}
- }
- b();
- console.log(a);
输出: 1
解释:
代码以全局变量a设置为1开始。在函数b()内部,声明了一个局部函数a,它暂时遮蔽了全局a。b()将10赋给局部a,但这不会影响全局a。console.log(a)语句打印未改变的全局a,结果是输出1。
问题6:给定以下数据集,按年龄对学生进行分组。
- const students = [
- { name: "Alice", age: 20 },
- { name: "Bob", age: 22 },
- { name: "Charlie", age: 19 },
- { name: "David", age: 22 },
- { name: "Eve", age: 20 },
- ];
解决方案:
- // 解决方案1:
- const result = Object.groupBy(students, ({age}) => age)
- console.log(result)
- // 解决方案2:
- const result = Object.groupBy(students, student => student.age)
- console.log(result)
输出:
- {
- 19: [{ name: "Charlie", age: 19 }],
- 20: [
- { name: "Alice", age: 20 },
- { name: "Eve", age: 20 }
- ],
- 22: [
- { name: "Bob", age: 22 },
- { name: "David", age: 22 }
- ]
- }
额外提示
在评论区中,有读者提到了另一个有趣的JavaScript陷阱:
- var a = 339491.55;
- var b = 678983.1;
- alert(a + b);
小心浮点数精度问题! 这个例子展示了JavaScript中浮点数运算可能出现的精度问题。
📌📌 更多JavaScript编程问题请访问:[Javascript Coding questions](https://dev.to/md_ashraf_dev_to/tricky-javascript-code-4c0c)
关键概念总结
变量提升(Hoisting):var声明的变量会被提升到作用域顶部
作用域差异:var是函数作用域,let/const是块作用域
立即调用函数表达式(IIFE):立即执行的匿名函数
函数声明提升:函数声明也会被提升
Object.groupBy():ES2024新特性,用于数组分组
