返回

JavaScript 中的五个神秘问题

前端

JavaScript 中的五个谜题

JavaScript 是当今最流行的编程语言之一,以其动态性和交互性而闻名。然而,这门语言也因其微妙而复杂的特性而臭名昭著。本文将探讨 JavaScript 中的五个谜题,揭示语言中一些经常被误解的概念。

问题 1:浏览器控制台上会打印什么?

var a = 5;
if (true) {
  var a = 10;
  console.log(a);  // 10
}
console.log(a);  // 10

这个问题展示了 JavaScript 中变量提升的概念。即使变量在块内重新声明,var 声明也会将变量提升到其所在作用域的顶部。因此,控制台将打印 10 两次。

问题 2:如果我们使用 let 或 const 代替 var,输出是否相同?

let a = 5;
if (true) {
  let a = 10;
  console.log(a);  // 10
}
console.log(a);  // 5
const a = 5;
if (true) {
  const a = 10;  // 报错:TypeError: Assignment to constant variable.
}
console.log(a);  // 5

使用 let 或 const 会阻止变量提升,并限制其作用域仅在声明它们的块内。因此,当使用 let 时,控制台将打印 10 和 5,而使用 const 时,则会出现错误。

问题 3:“newArray”中有哪三个值?

const newArray = [1, 2, 3].map((n) => {
  return n * 2;
});

console.log(newArray);  // [2, 4, 6]

乍一看,newArray 数组似乎包含 [2, 4, 6]。但是,由于箭头函数中的隐式返回,该数组实际上包含三个 undefined 值。这是因为箭头函数中没有大括号,这意味着自动插入一个返回语句。

问题 4:为什么箭头函数中的 this 指向 Window 对象?

const obj = {
  name: "JavaScript",
  printName: () => {
    console.log(this.name);  // undefined
  },
};

obj.printName();

箭头函数中的 this 关键字与它们所在的词法作用域有关,而不是其调用者的作用域。因此,obj.printName() 将输出 undefined,而不是预期的 “JavaScript”。

问题 5:这个闭包会做什么?

function createCounter() {
  let count = 0;
  return function() {
    return count++;
  };
}

const counter1 = createCounter();
const counter2 = createCounter();

console.log(counter1());  // 0
console.log(counter1());  // 1
console.log(counter2());  // 0
console.log(counter2());  // 1

这个函数返回一个闭包,该闭包可以访问其创建时的外部变量(count)。因此,counter1 和 counter2 拥有各自的私有计数器变量,并且不会相互影响。

理解这些谜题对于写出可靠且高效的 JavaScript 代码至关重要。通过掌握这些概念,你可以提高你的编程技能,并创建更有弹性、更易于维护的应用程序。