如何通过JavaScript面试:从A到Z的顶级问题
JavaScript开发者的面试不仅仅是对语法的考察。雇主希望看到对语言的深刻理解、其特性以及处理异步的能力。在本文中,我们将分析关键主题,帮助您自信地通过面试。我们将从基础概念到Node.js的高级主题,并结合实际代码示例进行探讨。
1. 基础:数据类型、hoisting和作用域
从基础开始。JavaScript是一种动态类型语言。理解var、let和const是必备的基础知识。
问题:var与let和const有什么区别?
var具有函数作用域,并且会提升(hoisting),初始值为undefined。let和const具有块级作用域,并且在声明之前不会被初始化(暂时性死区)。const禁止重新赋值,但不会使对象不可变。
hoisting示例:
console.log(a); // undefined (hoisting)var a = 5;
console.log(b); // ReferenceError: Cannot access 'b' before initializationlet b = 10;问题:什么是“提升”(hoisting)?
这是一种机制,变量和函数的声明在执行代码之前被移动到其作用域的顶部。通过function声明的函数会被整体提升,而变量只提升声明,不提升初始化。
2. 闭包和上下文(this)
闭包是JavaScript最强大的特性之一。它们允许函数记住创建时的词法环境。
问题:什么是闭包?请举例说明。
闭包是函数与其词法环境的组合。换句话说,内部函数可以访问外部函数的变量,即使外部函数已经执行完毕。
function createCounter() { let count = 0; return function() { count++; return count; };}
const counter = createCounter();console.log(counter()); // 1console.log(counter()); // 2问题:this在JavaScript中是如何工作的?
this的值取决于函数的调用方式,而不是声明位置。基本规则:
- 在全局上下文中(浏览器中)——
window,在Node.js中——global。 - 在对象的方法中——对象本身。
- 通过
new调用的函数中——新实例。 - 使用
call、apply、bind时——传入的对象。 - 在箭头函数中——
this取自外部词法上下文。
const obj = { name: 'Alice', greet() { console.log(this.name); }};
const greet = obj.greet;greet(); // undefined (丢失上下文)
const boundGreet = obj.greet.bind(obj);boundGreet(); // Alice3. 异步:Event Loop、Promise和async/await
JavaScript是单线程语言,但通过Event Loop高效处理异步操作。这是面试中最受欢迎的话题之一。
问题:什么是Event Loop?它是如何工作的?
Event Loop是一个无限循环,它监视调用栈(Call Stack)和任务队列(Task Queue / Microtask Queue)。如果调用栈为空,它会从微任务队列(Promise、MutationObserver)或宏任务队列(setTimeout、I/O)中取出第一个任务。
问题:微任务和宏任务有什么区别?
- 微任务: Promise.then/catch/finally,