如何通过JavaScript面试:高级水平热门问题
高级或中级JavaScript开发人员的面试不仅仅是语法检查。面试官希望看到你对语言运行机制的深刻理解,尤其是在Node.js环境中。在本文中,我们将分析经常引起困难的关键主题,并提供代码示例,帮助你自信地回答最棘手的问题。
1. 闭包 (Closures) 和词法环境
关于闭包的问题是经典问题。但在高级水平,不仅要给出定义,还要展示闭包如何与let、const以及在循环中工作。
问题:以下代码会输出什么,为什么?
for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100);}// 输出: 3, 3, 3问题在于var具有函数作用域,而不是块级作用域。当回调被调用时,循环已经结束,i等于3。解决方案是使用let(在每次迭代中创建新的绑定)或将调用包装在闭包中:
for (var i = 0; i < 3; i++) { (function(j) { setTimeout(() => console.log(j), 100); })(i);}// 输出: 0, 1, 2在Node.js中,闭包被广泛用于创建私有变量和函数工厂。例如,在编写中间件时:
function createLogger(prefix) { return function(message) { console.log(`[${prefix}] ${message}`); };}const infoLog = createLogger('INFO');infoLog('服务器已启动'); // [INFO] 服务器已启动2. 事件循环 (Event Loop) 和微任务 (Microtasks)
理解事件循环是评估的关键标准之一。面试官喜欢给出关于异步代码执行顺序的问题。
问题:console.log的执行顺序是什么?
console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
process.nextTick(() => console.log('4'));
console.log('5');
// 输出: 1, 5, 4, 3, 2解析:
console.log('1')和console.log('5')是同步的,首先执行。process.nextTick是优先级最高的微任务。它在当前阶段完成后立即执行。Promise.then也是微任务,但优先级略低于nextTick。setTimeout(fn, 0)是宏任务,在事件循环的下一个tick中执行。
对于Node.js,记住process.nextTick和setImmediate很重要。区别在于nextTick在任何I/O之前执行,而setImmediate在之后执行。
3. Promise 和异步迭代器 (Async/Await)
高级水平意味着能够处理Promise链、错误处理和并行执行。
问题:如何并行处理多个异步请求,并等待所有结果?
const fetchData = (id) => { return new Promise((resolve) => { setTimeout(() => resolve(`ID为${id}的数据`), id * 100); });};
async function getAllData() { const ids = [1, 2, 3]; const promises = ids.map(id => fetchData(id)); const results = await Promise.all(promises); console.log(results); // ['ID为1的数据', 'ID为2的数据', 'ID为3的数据']}
getAllData();重要细节:Promise.all在遇到第一个错误时会拒绝整个Promise。如果需要获取所有结果(即使有错误),请使用Promise.allSettled。这是面试中常见的主题,尤其是在