JavaScript中什么是闭包
概念:当一个内部函数被调用,就会形成闭包,闭包就是能够读取其他函数内部变量的函数
就是一个函数去访问了另外一个函数的中的变量的函数
例子:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>闭包</title> </head> <body> <script type="text/javascript"> //允许函数中嵌套函数 //内部函数允许调用外部函数的变量 //闭包就是能够读取其他函数内部变量的函数,内部函数和执行的上下文 var foo=function(){ var n=1; return function(){ n=n+1; console.log(n); } } var bar=foo(); bar(); //2 bar(); //3 var foobar=foo(); foobar(); //2 foobar(); //3 </script> </body> </html>
运行结果:
闭包作用:局部变量无法共享和长久的保存,而全局变量可能造成变量污染,所以我们希望有一种机制既可以长久的保存变量又不会造成全局污染。延伸变量的作用范围。
闭包特点:占用更多内存;不容易被释放
闭包用法:变量既想反复使用,又想避免全局污染如何使用?
1.定义外层函数,封装被保护的局部变量。
2.定义内层函数,执行对外部函数变量的操作。
3.外层函数返回内层函数的对象,并且外层函数被调用,结果保存在一个全局的变量中。
例子:
function getCounter() { var n = 1; var inner = function () { return n++; } return inner; } var getNum = getCounter(); getNum(); // n = 2; /*// 类似于 var n = 1; var getNum = function () { return n++; } getNum(); // n = 2; // 当调用getNum 就获取到了n的值*/
实用例子:看下面代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>闭包</title> </head> <button>按钮1</button> <button>按钮2</button> <button>按钮3</button> <button>按钮4</button> <button>按钮5</button> <button>按钮6</button> <button>按钮7</button> <button>按钮8</button> <button>按钮9</button> <body> <script type="text/javascript"> // 闭包的作用 var btn = document.querySelectorAll('button'); for (var i = 0; i < btn.length; i++) { btn[i].onclick = function() { alert(i); } } </script> </body> </html>
结果是,点击任何按钮都是弹出9,和我们预想的结果点击按钮1输出0,按钮3输出2,的不一样。
因为我们的function是一个一部任务,只有点击了才会执行,当循环结束了,i就等于4了,所以点击按钮,执行function但是已经等于4了。
解决方法:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>闭包</title> </head> <button>按钮1</button> <button>按钮2</button> <button>按钮3</button> <button>按钮4</button> <button>按钮5</button> <button>按钮6</button> <button>按钮7</button> <button>按钮8</button> <button>按钮9</button> <body> <script type="text/javascript"> // 闭包的作用 var btn = document.querySelectorAll('button'); for (var i = 0; i < btn.length; i++) { btn[i].index = i; btn[i].onclick = function() { alert(this.index); } } </script> </body> </html>
给每个btn都绑定一个index属性,并把i赋值给index,当点击了再获取。
当然也可以使用闭包来解决这个问题
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>闭包</title> </head> <button>按钮1</button> <button>按钮2</button> <button>按钮3</button> <button>按钮4</button> <button>按钮5</button> <button>按钮6</button> <button>按钮7</button> <button>按钮8</button> <button>按钮9</button> <body> <script type="text/javascript"> // 闭包的作用 var btn = document.querySelectorAll('button'); for (var i = 0; i < btn.length; i++) { (function (a) { btn[i].onclick = function() { alert(a); } })(i); } </script> </body> </html>
这里面写了一个立即执行函数,把i的值传入到立即执行函数里面,那么立即执行表达函数就有了一个变量
// 闭包的作用 var btn = document.querySelectorAll('button'); for (var i = 0; i < btn.length; i++) { // 立即执行表达函数 (function (a) { // 这里是一个function,其中有个变量a btn[i].onclick = function() { // 这里也是一个function alert(a); } })(i); // 把i传入立即执行函数 }
实用案例2:
var btn = document.querySelectorAll('button'); for (var i = 0; i < btn.length; i++) { setTimeout(function() { console.log(btn[i].innerHTML); }, 3000) }
for循环是一个同步任务,会立马执行,但是setTimeout是一个异步的,里面的function是一个回调函数,只有执行了setTimeout才会执行这个function,所以我执行这个setTimeout的时候 i 变成了9,我只有8个元素,所以出错了。
使用闭包:
var btn = document.querySelectorAll('button'); for (var i = 0; i < btn.length; i++) { (function(a) { setTimeout(function() { console.log(btn[a].innerHTML); }, 3000); })(i); }
标签:
JavaScript
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App