网站首页 > 技术文章 正文
什么是闭包?
百度百科定义:闭包就是能够读取其他函数内部变量的函数。创建闭包的通常方式,是在一个函数内部创建另一个函数
最常见的闭包结构如下
function aaa(){
var name = "xxx"
return function bbb(){
alert(name);
}
}
如上代码,bbb函数内可以访问aaa函数作用域内的变量
闭包解决了什么问题?
1. 可以读取函数内部的变量;
2. 让这些变量的值始终保持在内存中。不会在函数调用后被清除;
闭包的定义及其优缺点
闭包 是指有权访问另一个函数作用域中的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量
闭包的缺点就是常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。
闭包是javascript语言的一大特点,主要应用闭包场合主要是为了:设计私有的方法和变量。
一般函数执行完毕后,局部活动对象就被销毁,内存中仅仅保存全局作用域。但闭包的情况不同!
avascript的垃圾回收原理
(1)、在javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收;
(2)、如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。
使用闭包的好处
那么使用闭包有什么好处呢?使用闭包的好处是:
1.希望一个变量长期驻扎在内存中
2.避免全局变量的污染
3.私有成员的存在
全局变量
函数可以访问由函数内部定义的变量,如:
function myFunction() {
var a = 4;
return a * a;
}
函数也可以访问函数外部定义的变量,如:
var a = 4;
function myFunction() {
return a * a;
}
计数器困境
设想下如果你想统计一些数值,且该计数器在所有函数中都是可用的。
你可以使用全局变量,函数设置计数器递增:
var counter = 0;
function add() {
return counter += 1;
}
add();
add();
add();
// 计数器现在为 3
但问题来了,页面上的任何脚本都能改变计数器,即便没有调用 add() 函数。
如果我在函数内声明计数器,如果没有调用函数将无法修改计数器的值:
function add() {
var counter = 0;
return counter += 1;
}
add();
add();
add();
// 本意是想输出 3, 但事与愿违,输出的都是 1 !
JavaScript 嵌套函数
所有函数都有权访问全局作用域。
事实上,在 JavaScript 中,所有函数都有权访问它们“上面”的作用域。
JavaScript 支持嵌套函数。嵌套函数可以访问其上的作用域。
在本例中,内部函数 plus() 可以访问父函数中的 counter 计数器变量:
function add() {
var counter = 0;
function plus() {counter += 1;}
plus();
return counter;
}
这样即可解决计数器困境,如果我们能够从外面访问 plus() 函数。
我们还需要找到只执行一次 counter = 0 的方法。
我们需要闭包(closure)。
JavaScript 闭包
还记得函数自我调用吗?该函数会做什么?
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();
add();
add();
add();
// 计数器为 3
例子解释
变量 add 的赋值是自调用函数的返回值。
这个自调用函数只运行一次。它设置计数器为零(0),并返回函数表达式。
这样 add 成为了函数。最“精彩的”部分是它能够访问父作用域中的计数器。
这被称为 JavaScript 闭包。它使函数拥有“私有”变量成为可能。
计数器被这个匿名函数的作用域保护,并且只能使用 add 函数来修改。
闭包指的是有权访问父作用域的函数,即使在父函数关闭之后。
技巧1: 用闭包解决递归调用问题
function factorial(num) {
if(num<= 1) {
return 1
} else {
return num * factorial(num-1)
}
}
var anotherFactorial = factorial
factorial = null
anotherFactorial(4) // 报错 ,因为最好是return num* arguments.callee(num-1),arguments.callee指向当前执行函数,但是在严格模式下不能使用该属性也会报错,所以借助闭包来实现
// 使用闭包实现递归
function newFactorial = (function f(num){
if(num<1) {return 1}
else {
return num* f(num-1)
}
}) //这样就没有问题了,实际上起作用的是闭包函数f,而不是外面的函数newFactorial
技巧2:用闭包模仿块级作用域
es6没出来之前,用var定义变量存在变量提升问题:
for(var i=0;i<10; i++){
console.info(i)
}
alert(i) // 变量提升,弹出10
//为了避免i的提升可以这样做
(function () {
for(var i=0; i<10;i++){
console.info(i)
}
})()
alert(i) // underfined 因为i随着函数的退出,执行环境销毁,变量回收
- 上一篇: 详解 js 闭包(图文版) js闭包是什么
- 下一篇: 小白的前端练级之路——面向对象编程(闭包)
猜你喜欢
- 2025-06-23 JavaScript 开发者常犯的 10 个典型错误
- 2025-06-23 这7道问题可以检验你掌握Javascript的真正实力
- 2025-06-23 HarmonyOS NEXT 如何有效地进行内存管理和避免内存泄露?
- 2025-06-23 JS 函数柯里化(js函数柯里化面试题)
- 2025-06-23 《深入理解javascript原型和闭包系列》 知识点整理
- 2025-06-23 JS面试题突破:什么是闭包?(闭包 js)
- 2025-06-23 JavaScript闭包(javascript 闭包)
- 2025-06-23 “闭包到底是什么?90% 的前端开发者都没真正搞懂!”
- 2024-10-04 两个小案例让你深入理解 Javascript 闭包和作用域
- 2024-10-04 js中的闭包 js闭包的使用
你 发表评论:
欢迎- 596℃几个Oracle空值处理函数 oracle处理null值的函数
- 590℃Oracle分析函数之Lag和Lead()使用
- 578℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 573℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 570℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 563℃【数据统计分析】详解Oracle分组函数之CUBE
- 549℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 543℃Oracle有哪些常见的函数? oracle中常用的函数
- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端路由 (61)
- 前端数组 (73)
- 前端js面试题 (50)
- 前端定时器 (59)
- 前端懒加载 (49)
- 前端获取当前时间 (50)
- 前端接口 (50)
- Oracle RAC (76)
- oracle恢复 (77)
- oracle 删除表 (52)
- oracle 用户名 (80)
- oracle 工具 (55)
- oracle 内存 (55)
- oracle 导出表 (62)
- oracle 中文 (51)
- oracle的函数 (57)
- 前端调试 (52)
本文暂时没有评论,来添加一个吧(●'◡'●)