千家信息网

关于闭包的面试题有哪些

发表于:2025-11-07 作者:千家信息网编辑
千家信息网最后更新 2025年11月07日,本篇内容介绍了"关于闭包的面试题有哪些"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!每个 JavaS
千家信息网最后更新 2025年11月07日关于闭包的面试题有哪些

本篇内容介绍了"关于闭包的面试题有哪些"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

每个 JavaScript 程序员都必须知道闭包是什么。在 JavaScript 面试中,你很可能会被问到闭包的概念。

以下是 7 个有关 JavaScript 闭包的面试题,比较有挑战性。

不要查看答案或运行代码,看看自己的水平到底如何。做完这些题大约需要半小时左右。

1. 热身

有以下函数 clickHandler,immediate和delayedReload:

let countClicks = 0; button.addEventListener('click', function clickHandler() {   countClicks++; }); const result = (function immediate(number) {   const message = `number is: ${number}`;   return message; })(100); setTimeout(function delayedReload() {   location.reload(); }, 1000);

这3个函数中哪个能够访问外部范围变量?

答案:

  • clickHandler 能够从外部作用域访问变量 countClicks。

  • immediate 无法访问外部作用域中的任何变量。

  • delayedReload 从全局作用域(也就是最外层作用域)中访问全局变量 location。

2. 丢失的参数

下列代码输出什么:

(function immediateA(a) {   return (function immediateB(b) {     console.log(a); // => ?   })(1); })(0);

答案:

  • 输出为:0

  • 用参数 0 调用 immediateA,因此 a 参数为 0。

  • immediateB 函数嵌套在 immediateA 函数中,是一个闭包,它从外部 immediateA作用域中得到 a 变量,其中 a 为 0。因此 console.log(a) 的输出为 0。

3. 谁是谁

下面的代码将会输出什么内容?

let count = 0; (function immediate() {   if (count === 0) {     let count = 1;     console.log(count); // 输出什么?   }   console.log(count); // 输出什么? })();

答案:

  • 输出 1 和 0

  • 第一个语句 let count = 0 声明了一个变量 count。

  • immediate() 是一个闭包,它从外部作用域得到 count 变量。在 immediate() 函数作用域内, count 是 0。

但是,在条件内,另一个 let count = 1 声明了局部变量 count,该变量覆盖了作用域之外的 count。第一个 console.log(count) 输出 1。

第二个 console.log(count) 输出为 0 ,因为这里的 count 变量是从外部作用域访问的。

4. 棘手的闭包

下列代码输出什么:

for (var i = 0; i < 3; i++) {   setTimeout(function log() {     console.log(i); // => ?   }, 1000); }

答案输出:

  • 3, 3, 3。

  • 代码分为两个阶段执行。

阶段1:

  • for() 重复 3 次。在每次循环都会创建一个新函数 log(),该函数将捕获变量 i。setTimout() 安排log() 在 1000 毫秒后执行。

  • 当 for() 循环完成时,变量 i 的值为 3。

阶段2:

第二阶段发生在 1000ms 之后:

  • setTimeout() 执行预定的 log() 函数。log() 读取变量 i 当前的值 3,并输出 3

  • 所以输出 3, 3, 3。

5. 错误的信息

下面的代码将会输出什么:

function createIncrement() {   let count = 0;   function increment() {      count++;   }    let message = `Count is ${count}`;   function log() {     console.log(message);   }      return [increment, log]; }  const [increment, log] = createIncrement(); increment();  increment();  increment();  log(); // => ?

答案:

输出:'Count is 0'

  • increment() 函数被调用 3 次,将 count 增加到 3。

  • message 变量存在于 createIncrement() 函数的作用域内。其初始值为 'Count is 0'。但即使 count 变量已经增加了几次,message 变量的值也始终为 'Count is 0'。

  • log() 函数是一个闭包,它从 createIncrement() 作用域中获取 message 变量。console.log(message) 输出录'Count is 0'到控制台。

6. 重新封装

下面的函数 createStack() 用于创建栈结构:

function createStack() {   return {     items: [],     push(item) {       this.items.push(item);     },     pop() {       return this.items.pop();     }   }; }  const stack = createStack(); stack.push(10); stack.push(5); stack.pop(); // => 5  stack.items; // => [10] stack.items = [10, 100, 1000]; // 栈结构的封装被破坏了

它能正常工作,但有一个小问题,因为暴露了 stack.items 属性,所以任何人都可以直接修改 items 数组。

这是一个大问题,因为它破坏了栈的封装:应该只有 push() 和 pop() 方法是公开的,而 stack.items 或其他任何细节都不能被访问。

使用闭包的概念重构上面的栈实现,这样就无法在 createStack() 函数作用域之外访问 items 数组:

function createStack() {   // 把你的代码写在这里 }  const stack = createStack(); stack.push(10); stack.push(5); stack.pop(); // => 5  stack.items; // => undefined

答案:

以下是对 createStack() 的重构:

function createStack() {   const items = [];   return {     push(item) {       items.push(item);     },     pop() {       return items.pop();     }   }; }  const stack = createStack(); stack.push(10); stack.push(5); stack.pop(); // => 5  stack.items; // => undefined

items 已被移至 createStack() 作用域内。

这样修改后,从 createStack() 作用域的外部无法访问或修改 items 数组。现在 items 是一个私有变量,并且栈被封装:只有 push() 和 pop() 方法是公共的。

push() 和 pop() 方法是闭包,它们从 createStack() 函数作用域中得到 items变量。

7. 智能乘法

编写一个函数 multiply() ,将两个数字相乘:

function multiply(num1, num2) {   // 把你的代码写在这里... }

要求:

如果用 2 个参数调用 multiply(num1,numb2),则应返回这 2 个参数的乘积。

但是如果用 1个参数调用,则该函数应返回另一个函数:const anotherFunc = multiply(num1) 。返回的函数在调用 anotherFunc(num2) 时执行乘法 num1 * num2。

multiply(4, 5); // => 20 multiply(3, 3); // => 9  const double = multiply(2); double(5);  // => 10 double(11); // => 22

答案:

以下是 multiply() 函数的一种实现方式:

function multiply(number1, number2) {   if (number2 !== undefined) {     return number1 * number2;   }   return function doMultiply(number2) {     return number1 * number2;   }; }  multiply(4, 5); // => 20 multiply(3, 3); // => 9  const double = multiply(2); double(5);  // => 10 double(11); // => 22

如果 number2 参数不是 undefined,则该函数仅返回 number1 * number2。

但是,如果 number2 是 undefined,则意味着已经使用一个参数调用了 multiply() 函数。这时就要返回一个函数 doMultiply(),该函数稍后被调用时将执行实际的乘法运算。

doMultiply() 是闭包,因为它从 multiply() 作用域中得到了number1 变量。

"关于闭包的面试题有哪些"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

函数 变量 输出 作用 闭包 代码 参数 答案 阶段 面的 封装 乘法 内容 数组 方法 两个 全局 只有 实际 更多 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 mongodb数据库的认识 云为智合网络技术深圳 网络安全名人故事 网络安全自学 福建中职学考网络技术真题 滁州网站建设软件开发 平潭资源交易中心网络安全责任 给我查查软件数据库 徐汇区一站式软件开发诚信合作 宝山区进口软件开发产品介绍 服务器重启数据库正在恢复 数据库技术与应用专业 高拍仪连接sql数据库 北京世纪华康网络技术有限公司 常州软件开发销售价格 即墨区热点网络技术服务中心 滨江网络安全管理员 维普数据库可以跨库吗 查看服务器端口是否在启用 黄浦区营销网络技术包括什么 手机开设服务器 超星电子图书数据库在哪儿 增值税发票访问数据库失败 数据库方面的培训 广东网络安全等级测评 数据库怎么创建登录名 文科女生学计算机网络技术好吗 中华人民共和国网络安全法4章 长宁区市场软件开发有哪些 网络安全工作专题会议程
0