发布于 2026-01-05 4 阅读
0

谷歌提出的一个棘手的 JavaScript 面试题

谷歌提出的一个棘手的 JavaScript 面试题

以下将简要解释并给出一些解答,解答一个经常在开发者面试中被问到的常见 JavaScript 问题。这个问题通常如下所示:

// interviewer: what will the following code output?
const arr = [10, 12, 15, 21];
for (var i = 0; i < arr.length; i++) {
  setTimeout(function() {
    console.log('Index: ' + i + ', element: ' + arr[i]);
  }, 3000);
}

这个问题涉及以下主题:闭包setTimeout作用域

这个问题的正确答案是:

Index: 4, element: undefined
Index: 4, element: undefined
Index: 4, element: undefined
Index: 4, element: undefined

如果这与你的预期不符,那么希望本文的其余部分能够解释为什么在 JavaScript 中会出现这种情况。

为什么这个问题如此热门?

一位 Reddit 用户提到,他在亚马逊的开发者面试中被问到了这个问题。我自己也曾在面试中被问到过类似的闭包和循环问题——甚至在谷歌的面试中也被问到过。

这个问题旨在测试你对一些重要的 JavaScript 概念的了解,而且由于 JavaScript 语言的工作方式,这实际上是你在工作中经常会遇到的问题——即需要在循环中使用 setTimeout 或某种异步函数。

对函数式/块级作用域、匿名函数、闭包和立即执行函数表达式 (IIFE) 的扎实理解,绝对能让你成为一名更优秀的 JavaScript 开发人员,并对你未来的面试有所帮助。

解决方案

我曾在CoderbytefreeCodeCamp上写过这类挑战

这是因为 `setTimeout` 函数创建了一个函数(闭包),该函数可以访问其外部作用域,也就是包含索引 `i` 的循环。3 秒后,该函数执行并打印出 `i` 的值,此时 `i` 的值是 4,因为循环遍历了 `0`、`1`、`2`、`3`、`4`,最终在 `4` 处停止。`arr[4]` 不存在,这就是为什么你会得到 `undefined` 的原因。

这个问题有两种常见的解决方案。一种是将所需的参数传递给内部函数,另一种是使用 ES6。

const arr = [10, 12, 15, 21];
for (var i = 0; i < arr.length; i++) {
  // pass in the variable i so that each function 
  // has access to the correct index
  setTimeout(function(i_local) {
    return function() {
      console.log('The index of this number is: ' + i_local);
    }
  }(i), 3000);
}
const arr = [10, 12, 15, 21];
for (let i = 0; i < arr.length; i++) {
  // using the ES6 let syntax, it creates a new binding
  // every single time the function is called
  // read more here: http://exploringjs.com/es6/ch_variables.html#sec_let-const-loop-heads
  setTimeout(function() {
    console.log('The index of this number is: ' + i);
  }, 3000);
}

Reddit 帖子下的一位用户也给出了类似的答案。此外, Stack Overflow 上也有一位用户对闭包进行了很好的解释。

这常常会让 JavaScript 或函数式编程新手感到困惑。这是由于对闭包的误解造成的。闭包不仅仅是传递变量的值,甚至不仅仅是传递对变量的引用。闭包捕获的是变量本身!

感谢阅读!可以去Coderbyte练习编程哦 :)

本文最初发表于Medium

文章来源:https://dev.to/coderbyte/a-tricky-javascript-interview-question-asked-by-google-3gnf