闭包+面试真题

embedded/2024/9/24 17:03:23/

对闭包的理解

闭包是内层函数使用外层变量
(子级可以访问父级的变量,但是父级不可以访问子级的)

闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,创建的函数可以访问到当前函数的局部变量。

闭包有两个常用的用途;

  • 闭包的第一个用途是使我们在函数外部能够访问到函数内部的变量。通过使用闭包,可以通过在外部调用闭包函数,从而在外部访问到函数内部的变量,可以使用这种方法来创建私有变量。
  • 闭包的另一个用途是使已经运行结束的函数上下文中的变量对象继续留在内存中,因为闭包函数保留了这个变量对象的引用,所以这个变量对象不会被回收。
    这是因为 JavaScript 的垃圾回收机制会检查对象是否还被引用,如果没有引用,则认为该对象是垃圾,可以被回收。而闭包的内部函数可能会继续访问外部函数的变量。只有当闭包函数本身也被销毁时,其引用的外部作用域才会被释放。
    比如,函数 A 内部有一个函数 B,函数 B 可以访问到函数 A 中的变量,那么函数 B 就是闭包。
function A() {let a = 1;window.B = function () {console.log(a);};
}
A();
B(); // 1

面试真题

1. 基础题

在 JS 中,闭包存在的意义就是让我们可以间接访问函数内部的变量。经典面试题:循环中使用闭包解决 var 定义函数的问题

for (var i = 1; i <= 5; i++) {setTimeout(function timer() {console.log(i);}, i * 1000);
}

首先因为 setTimeout 是个异步函数,所以会先把循环全部执行完毕,这时候 i 就是 6 了,所以会输出一堆 6。解决办法有三种:

  • 第一种是使用闭包的方式
for (var i = 1; i <= 5; i++) {(function (j) {setTimeout(function timer() {console.log(j);}, j * 1000);})(i); // 把i作为参数传递给前面括号里的j
}

使用立即执行函数包裹 setTimeout 的回调函数,能够创建一个闭包
在上述代码中,首先使用了立即执行函数i 传入函数内部,这个时候值就被固定在了参数 j 上面不会改变,当下次执行 timer 这个闭包的时候,就可以使用外部函数的变量 j,从而达到目的。

  • 第二种就是使用 setTimeout 的第三个参数,这个参数会被当成 timer 回调函数的参数传入。
for (var i = 1; i <= 5; i++) {setTimeout(function timer(j) {console.log(j);},i * 1000,i);
}
  • 第三种就是使用 let 定义 i 了来解决问题了,这个也是最为推荐的方式
for (let i = 1; i <= 5; i++) {setTimeout(function timer() {console.log(i);}, i * 1000);
}

2. 变形题

/* TASK A1In the following code, what will be printed to console if a user clicks the first and fourth button? Why?
*/var nodes = document.getElementsByTagName("button");for (var i = 0; i < nodes.length; i++) {nodes[i].addEventListener("click", function () {console.log("You clicked element #" + i);});}

输出的是 nodes.length的值;

因为var生命的是函数作用域

解决:
方法1:let
方法2:闭包

 var nodes = document.getElementsByTagName("button");for (var i = 0; i < nodes.length; i++) {(function (i) {nodes[i].addEventListener("click", function () {console.log("You clicked element #" + i);});})(i);}

http://www.ppmy.cn/embedded/112289.html

相关文章

15_分布式数据结构

菜鸟&#xff1a; 老鸟&#xff0c;我最近在处理大量数据的时候遇到了瓶颈&#xff0c;单台服务器的内存和计算能力都不够用了。你知道有什么方法可以解决这个问题吗&#xff1f; 老鸟&#xff1a; 嗯&#xff0c;这种情况很常见。你可以考虑使用分布式数据结构。听说过吗&a…

Anaconda配置

2024_Anaconda更换清华源 Python项目依赖包生成requirements.txt pip freeze > requirements.txt pip install -r requirements.txtAnaconda安装以及修改环境默认位置图文教程 使用 Conda 创建和删除指定路径的虚拟环境

Vue: 创建vue项目

目录 一.创建项目 二.项目添加 三.添加成功 一.创建项目 打开本机终端输入npm create vuelatest 二.项目添加 1. 项目名称&#xff1a; Project name: one_vue 2.是否添加TypeScript支持&#xff1a;Add TypeScript? Yes 3.是否添加JSX支持&#xff1a;Add JSX Suppor…

线结构光测量系统标定--导轨

光平面标定原理可查看之前的博文《光平面标定》&#xff0c;光条中心提取可参考线结构光专栏光条中心提取系列的文章&#xff0c;相机标定参考相机标定专栏中的博文。&#xff08;欢迎进Q群交流&#xff1a;874653199&#xff09; 线结构光测量系统(指一个线结构光传感器与一个…

openssl下载和创建证书

下载&#xff1a;https://slproweb.com/products/Win32OpenSSL.html 参考&#xff1a;保姆级OpenSSL下载及安装教程-CSDN博客 生成证书 使用OpenSSL生成SSL证书的教程-CSDN博客

【R语言】删除数据框中所有行中没有大于200的数值的行

在Perl中还需要循环按行读入文件&#xff0c;而在R中&#xff0c;一行代码解决问题&#xff1a; df <- df[apply(df, 1, function(x) any(x > 200)), ]这是一个使用apply函数对数据框df进行操作的表达式。apply函数用于对数据框、矩阵或数组进行元素级别的操作。 df&am…

CentOS详细解析及其配置方法

CentOS&#xff0c;作为一款基于Red Hat Enterprise Linux&#xff08;RHEL&#xff09;源代码构建的开源类服务器操作系统&#xff0c;自发布以来&#xff0c;凭借其卓越的稳定性、安全性和易用性&#xff0c;在企业级Linux发行版中占据了重要地位。以下是对CentOS的详细解析及…

实战千问2大模型第三天——Qwen2-VL-7B(多模态)视频检测和批处理代码测试

画面描述:这个视频中,一位穿着蓝色西装的女性站在室内,背景中可以看到一些装饰品和植物。她双手交叉放在身前,面带微笑,似乎在进行一场演讲或主持活动。她的服装整洁,显得非常专业和自信。 一、简介 阿里通义千问开源新一代视觉语言模型Qwen2-VL。其中,Qwen2-VL-72B在大…