什么是闭包?闭包有啥作用?闭包的应用有啥?内存优化?
什么是闭包?闭包的应用有哪些?
是不是很多人一开始所了解的闭包是一个函数套着另一个函数,然后其他的函数可以引用里面的函数的变量(很久之前俺就是这么理解的)?看完这篇文章后,球球泥们不要再这么回答了好嘛!(憨憨叉腰)
下面先来看看闭包是啥,它有啥用呢?
其中提到的私有上下文或执行上下文如果有不懂的地方,可以看看这个博:https://www.jianshu.com/p/82691a18562d
闭包及其作用
闭包:它是函数运行时所产生的机制,函数执行会形成一个全新的私有上下文,可以保护里面的私有变量和外界互不干扰,这就是所谓的保护机制!如果当前上下文不被出栈释放,这样私有变量及它的值也不会被释放掉,这就是保存机制!
所以闭包的作用是:保存&保护。
简单来说,函数执行会形成一个私有上下文,如果私有上下文中的某些内容被私有上下文以外的其他事物所占有,当前上下文就不能被出栈释放,那么它里面的私有变量就被保存起来了。同时,在代码执行过程中,它里面的私有变量和外界互不干扰,我对私有变量的一些操作只是操作私有的,不影响外界的变量值,这种情况叫闭包。
我看到有篇博客里写的特别搞笑且通俗易懂,说闭包就是你的老婆出轨隔壁老王了, 老王可以很轻易的通过你老婆了解你家里的情况,只要你还没离婚,这种状况就一直会持续下去……
闭包的应用
聊完了闭包的作用,那么它的应用有哪些呢?你如果只简单的学习了js的一些基础语法,想继续提升一下,那么就请麻溜的看下去!
1、单例设计模式
单例设计模式:用单独的实例来管理当前事物的属性和方法(可以理解为产生一个类的唯一实例),基于闭包管控的单例设计模式称为高级单例设计模式,以此来实现模块划分,这也是最早的模块化思想。
看下面的代码就是用闭包思想实现的:
let moduleA = (function(){function AAA(){};function BBB(){};return {A //如果想要把需要供外面访问的变量和方法,那就写在return中}
})();
moduleA.AAA(); //调用模块A中的AAA方法
你看出闭包思想怎么体现了吗?你瞅瞅,这个moduleA 的方法AAA在外面都被调用了,那moduleA 占用的内存能释放不能?铁定不能啊!早期多人开发的时候,好多人起一样的变量名,会造成变量污染的,然后就用这种方法好了很多!
2、惰性函数
惰性函数:函数执行的分支只会在函数第一次调用的时候执行,在第一次调用过程中,该函数会被覆盖为另一个按照合适方式执行的函数,下次执行的时候就执行覆盖后的函数。
惰性思想,就是懒呗,执行过一次的东西,如果第二部执行还是一样的效果,那就不要重复完整的执行第二遍了。
举一个栗子!假设你想获取浏览器中的样式,你能用啥方法?考虑兼容呢?
·getComputedStyle方法,该属性是兼容火狐谷歌,不兼容IE6-8!
·currentStyle方法,该属性只兼容IE,不兼容火狐和谷歌!
·style 更不行了哇!只能获取行内样式(就是写在html标签里的)!
好,咱们来考虑下怎么在兼容浏览器的情况下获取样式,首先用普通方法来写:
function getStyle(element, cssName){ if('getComputedStyle' in window) //in 判断某个属性是否为当前对象的属性,就是找window里有没有getComputedStyle属性,如果有,那就是谷歌或者火狐等浏览器,就执行下面这个方法return window.getComputedStyle(element)[cssName];//没有getComputedStyle就是ie浏览器呗,就执行currentStyle方法,return element.currentStyle[cssName];
}
getStyle(document.body,'margin')
没毛病吧?下面看看用惰性思想来实现的代码:
function getStyle(element, cssName){ if('getComputedStyle' in window){ //in 判断某个属性是否为当前对象的属性getStyle = function(element, cssName){return window.getComputedStyle(element)[cssName];} }else{getStyle = function(element, cssName){return element.currentStyle[cssName];} }return getStyle(element, cssName) //为了第一次执行下面的获取margin样式也能拿到window下的样式。
}
getStyle(document.body,'margin')
getStyle(document.body,'padding')
getStyle(document.body,'height')
用惰性思想改完后的代码的getStyle是一个全局函数,在浏览器关闭时才会释放,里面的function被返回给了getStyle,所以形成了一个闭包。
咱代码第一次执行的时候,如果遇到的有getComputedStyle属性,那就是谷歌它们呗,和上面没用惰性思想的代码相比,就是把function匿名函数重新赋值给getStyle了,接下来都在谷歌浏览器执行这个方法了,就不需要再判断一次了!多省事!
懂了后做做下面的题呗?看看输出啥?这题也是惰性思想的体现!
3、柯里化函数
柯里化函数思想:利用闭包保存机制,把一些信息预先存储起来(预处理的思想)
首先问一个问题,这也是百度问过的一题:
实现函数fn,让其具有如下功能:
该怎么写呢?是不是可以把fn(1,2)先执行了,执行后的返回值传入实参3继续执行呢?答案如下:
function fn(...outerArgs){return function(...innerArgs){let args = outerArgs.concat(innerArgs); //args:将外层和里层传递的所有值都合并在一起return args.reduce( (n,item) => n+item );};
}
//——————
let res = fn(1,2)(3);
console.log(res) //输出6//————下面的就相当于:
let f = fn(1,2);
console.log(f(3)); //输出6
4、compose函数
compose函数:组合式函数,把多层函数嵌套调用扁平化!
我们又要来看一个例题了,毕竟实践是最好的老师~
又是来自百度的面试题:
实现函数fn,让其具有如下功能:
使用compose:利用柯里化思想存储预处理的值,然后利用reduce函数遍历每一个函数,把上一次函数执行的返回值作为实参传递给下一个函数执行。答案如下:
function compose(...funcs){ //funcs:存储按照顺序执行的函数(或函数数组,例如【fn1,fn2,fn3】)return function(...args){ //args:存储第一个函数执行需要传递的实参信息(数组)-->20if(funcs.length===0) return args;if(funcs.length===1) return funcs[0](...args);return funcs.reduce((N,func) => {//第一次N的值:是第一次函数执行的实参,func是第一个函数//第二次N的值:上一次func执行的返回值,作为实参传递给下一个函数执行return Array.isArray(N)?func(...N):func(N); //说到这,问个题外问题:判断是数组的方法有哪些?},args);};
}
let res = compose(fn1,fn2,fn3,fn4)(20);
console.log(res);
5、函数的防抖和节流
请看:https://blog.csdn.net/Dracolan/article/details/107790150
还有很多地方也用到了闭包机制,比如redux源码里~那就是后话了!
闭包的优缺点
优点:就是它的作用,保护和保存。
缺点:闭包会产生不销毁的上下文,会导致栈/堆内存消耗过大,有时候也会导致内存泄漏等,影响页面的运行性能,所以在真实项目中,要合理应用闭包!
所以我们需要内存优化:
内存优化
栈内存
栈内存(执行上下文):
一般情况下,函数执行完,所形成的上下文会被出栈释放掉。
特殊情况:当前上下文中的某些内容被上下文以外的事物占用了,此时不能出栈释放。
全局上下文:加载页面时创建,只有在关闭页面才会被释放。
堆内存
堆内存:
浏览器的垃圾回收机制:
1、引用计数(以IE为主):在某些情况下会导致计数混乱,这样会造成内存不能被释放(内存泄漏)。
2、检测引用(以谷歌为主):浏览器在空闲的时候会依次检测所有的堆内存,把没有被任何事物占用的内存释放掉,以此来优化内存。
可以手动释放内存,其实就是解除占用(手动赋值为null即可)。
完结撒花
如果你觉得这篇文章对你有用的话,那就请点个赞赞~~~~~
什么是闭包?闭包有啥作用?闭包的应用有啥?内存优化?相关推荐
- 闭包的两大作用:保存/保护
闭包的概念 函数执行时形成的私有上下文EC(FN),正常情况下,代码执行完会出栈后释放;但是特殊情况下,如果当前私有上下文中的某个东西被上下文以外的事物占用了,则上下文不会出栈释 放, 从而形成不销 ...
- python闭包到底有什么作用
本文转载于https://blog.csdn.net/qq_27825451/article/details/79964128,并对代码格式做了修正. 1.global关键字的作用 如果在函数中需要修 ...
- 闭包的概念,作用,和优缺点
闭包的概念 闭包就是能读取其他函数内部变量的函数. 也可以简单的理解为:"定义在一个函数内部的函数" 闭包的形式 //在执行fn1时,其返回值是一个函数,即fn2,所以再一次执行的 ...
- 浅谈“闭包”,什么才是“闭包”思想!—— javascript
先看一个简单小案例: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML&g ...
- 什么是闭包?闭包产生的原因以及闭包有哪些表现形式
闭包的定义: JavaScript红宝书上对于闭包的定义:闭包是指有权访问另外一个函数作用域中的变量的函数, MDN 对闭包的定义为:闭包是指那些能够访问自由变量的函数. (其中自由变量,指在函数中使 ...
- python闭包详解函数_Python闭包详解
首先给出闭包函数的必要条件: 闭包函数必须返回一个函数对象 闭包函数返回的那个函数必须引用外部变量(一般不能是全局变量),而返回的那个函数内部不一定要return 几个典型的闭包例子: #ENV> ...
- 【Groovy】闭包 Closure ( 自定义闭包参数 | 自定义单个闭包参数 | 自定义多个闭包参数 | 闭包参数默认值指定 )
文章目录 一.自定义闭包参数列表 1.定义一个自定义参数的闭包 2.定义多个自定义参数的闭包 3.为闭包参数指定默认值 二.完整代码示例 一.自定义闭包参数列表 如果要向 闭包 中 , 传递多个参数 ...
- php _invoke 闭包,PHP新特性之闭包、匿名函数
闭包 闭包是什么? 1).闭包和匿名函数在PHP5.3中被引入. 2).闭包是指在创建时封装函数周围状态的函数,即使闭包所在的环境不存在了,闭包封装的状态依然存在,这一点和Javascript的闭包特 ...
- python闭包的应用场景_Python闭包函数定义与用法分析
python函数的闭包怎么理解小编憎恨离别.但若,离别能让你牵挂,小编愿意离开你. 1. 闭包的概念 首先还得从基本概念说起,什么是闭包呢?来看下维基上的解释: 复制代码代码如下: 在计算机科学中,闭 ...
最新文章
- 基于Erlang语言的视频相似推荐系统 | 深度
- 数据挖掘如何分箱以及如何对每个箱子中的数据进行平滑处理
- Activity的setContentView的流程
- Eclipse 启动问题:'Initilizing Java Tooling' has encountered a problem(。。。)
- 携程在线风控系统架构
- centos7开启vnc服务_Centos7 VNC远程桌面服务安装配置
- 二叉树的二叉链表存储结构构建以及先序遍历
- [Qt教程] 第24篇 数据库(四)SQL查询模型QSqlQueryModel
- leetcode049. 最后一块石头的重量 II
- 三、Unity中的鼠标、键盘的获取
- 软件用户体验非常好的前端设计
- 信息学奥赛一本通 1016:整型数据类型存储空间大小 | OpenJudge NOI 1.2 01
- java知识点八:时间日期类
- java rfid 写入_RFID读写器函数JAVA调用示例
- Java URLDecoder和URLEncoder
- 转载“用USBOOT制作DOS启动盘”
- Windows:Win10 Dell笔记本禁用触摸板
- 阻止计算机访问注册表,电脑中毒了,注册表打不开了,提示注册表已被管理员禁止,这该怎么办...
- 作业07-Java GUI编程
- Java根据当前第几周获取周一和周日的日期方法
热门文章
- 计算机键盘输入法基础知识,电脑打字入门基础知识
- C语言768kb未压缩图片,若一幅图像的量化字长为16位,分辨率为800*600,它不经压缩占用的存储容量是()字节。A.690000B.1 - 试题答案网问答...
- Java字符串格式化详解
- VLookup怎么用详细步骤?VLookup函数的使用方法及实例
- Ubuntu 开机显示 initramfs 进不了系统
- 【Git版本控制管理】Gitee(码云)和GitHub的使用
- cloud云技术简介
- 其他网页可以使用,但百度首页打不开,百度搜索无法使用,怎么办
- Java选择题(十八)
- arm芯片,远程空中升级程序技术方案