JavaScript面试挑战:探索原型、闭包与事件循环

0 下载量 54 浏览量 更新于2024-08-30 收藏 175KB PDF 举报
"这篇文章主要介绍了8个有意思的JavaScript面试题,涵盖了变量作用域、函数调用、闭包、事件循环、微任务以及对象属性等方面的知识。通过这些题目,可以帮助开发者加深对JavaScript核心概念的理解,避免因知识盲点导致的错误。" 在JavaScript中,一些关键的概念经常会在面试中被用来测试候选人的理解程度。以下是对给出的面试题的解答和相关知识点解析: 问题1:浏览器控制台上会打印什么? ```javascript var a = 10; function foo() { console.log(a); // ?? var a = 20; } foo(); ``` 答案:`undefined`。这涉及到JavaScript的作用域和变量提升(Hoisting)。在函数内部,`var a`会创建一个新的局部变量,并覆盖全局的`a`。由于变量提升,`console.log(a)`在执行前会被提升到函数顶部,此时`a`还未被赋值,所以打印`undefined`。 问题2:如果我们使用`let`或`const`代替`var`,输出是否相同? ```javascript var a = 10; function foo() { console.log(a); // ?? let a = 20; } foo(); ``` 答案:不同。使用`let`时,会出现块级作用域,控制台会抛出错误,因为尝试重新声明已存在的变量`a`。`const`也会抛出错误,因为它不允许重新赋值。 问题3:“`newArray`”中有哪些元素? ```javascript var array = []; for (var i = 0; i < 3; i++) { array.push(() => i); } var newArray = array.map(el => el()); console.log(newArray); // ?? ``` 答案:`[0, 1, 2]`。这里涉及到了闭包。每个箭头函数都捕获了外部作用域中的`i`的引用,而不是拷贝它的值。当`map`函数调用每个回调时,`i`已经变成了3,所以它们都返回3。但闭包使得每个函数都有自己的作用域,所以它们都能访问到各自的`i`值。 问题4:如果我们在浏览器控制台中运行`foo`函数,是否会导致堆栈溢出错误? ```javascript function foo() { setTimeout(foo, 0); // 是否存在堆栈溢出错误? } ``` 答案:不会。这是因为`setTimeout`将函数添加到事件队列中,而不是立即执行。当当前执行上下文(函数调用)完成后,事件循环会处理队列中的任务,这样就不会形成无限递归,因此没有堆栈溢出。 问题5:如果在控制台中运行以下函数,页面(选项卡)的UI是否仍然响应? ```javascript function foo() { return Promise.resolve().then(foo); } ``` 答案:是的,页面UI仍然响应。这个函数创建了一个无限的异步链,每个`then`都会注册一个微任务。尽管它们形成无限循环,但微任务不会阻塞主线程,所以UI仍然可以更新。 问题6:我们能否以某种方式为下面的语句使用展开运算而不导致类型错误 ```javascript var obj = {x: 1, y: 2, z: 3}; [obj]; // TypeError ``` 答案:可以。我们可以使用`Array.from()`或者扩展运算符与数组结合来避免类型错误: ```javascript Array.from(obj); // ['x', 'y', 'z'] [...Object.keys(obj)]; // ['x', 'y', 'z'] ``` 问题7:运行以下代码片段时,控制台上会打印什么? ```javascript var obj = {a: 1, b: 2}; Object.setPrototypeOf(obj, {c: 3}); Object.defineProperty(obj, "d", {value: 4, enumerable: false}); // what properties will be printed when we run the for-in loop? for (let prop in obj) { console.log(prop); } ``` 答案:`'a'`, `'b'`。`for-in`循环只遍历可枚举属性,`c`是通过`setPrototypeOf`设置的,不是可枚举的,所以不会被打印。`d`虽然有值,但`enumerable`设置为`false`,所以也不会被打印。 这些问题旨在揭示JavaScript中的一些关键概念,如作用域、闭包、异步处理、对象属性和原型链,这些都是开发者日常工作中需要深入理解的。