柏虎资源网

专注编程学习,Python、Java、C++ 教程、案例及资源

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();

输出:

o 第一个console.log:undefined

o 第二个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();

输出:

o 第一个console.log:5

o 第二个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);
})();

输出:

o 第一个console.log:undefined

o 第二个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中浮点数运算可能出现的精度问题。



关键概念总结

1. 变量提升(Hoisting):var声明的变量会被提升到作用域顶部

2. 作用域差异:var是函数作用域,let/const是块作用域

3. 立即调用函数表达式(IIFE):立即执行的匿名函数

4. 函数声明提升:函数声明也会被提升

5. Object.groupBy():ES2024新特性,用于数组分组

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言