什么是闭包?闭包的应用有哪些?

是不是很多人一开始所了解的闭包是一个函数套着另一个函数,然后其他的函数可以引用里面的函数的变量(很久之前俺就是这么理解的)?看完这篇文章后,球球泥们不要再这么回答了好嘛!(憨憨叉腰)
下面先来看看闭包是啥,它有啥用呢?
其中提到的私有上下文或执行上下文如果有不懂的地方,可以看看这个博: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即可)。

完结撒花

如果你觉得这篇文章对你有用的话,那就请点个赞赞~~~~~

什么是闭包?闭包有啥作用?闭包的应用有啥?内存优化?相关推荐

  1. 闭包的两大作用:保存/保护

    闭包的概念 函数执行时形成的私有上下文EC(FN),正常情况下,代码执行完会出栈后释放;但是特殊情况下,如果当前私有上下文中的某个东西被上下文以外的事物占用了,则上下文不会出栈释  放, 从而形成不销 ...

  2. python闭包到底有什么作用

    本文转载于https://blog.csdn.net/qq_27825451/article/details/79964128,并对代码格式做了修正. 1.global关键字的作用 如果在函数中需要修 ...

  3. 闭包的概念,作用,和优缺点

    闭包的概念 闭包就是能读取其他函数内部变量的函数. 也可以简单的理解为:"定义在一个函数内部的函数" 闭包的形式 //在执行fn1时,其返回值是一个函数,即fn2,所以再一次执行的 ...

  4. 浅谈“闭包”,什么才是“闭包”思想!—— javascript

    先看一个简单小案例: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML&g ...

  5. 什么是闭包?闭包产生的原因以及闭包有哪些表现形式

    闭包的定义: JavaScript红宝书上对于闭包的定义:闭包是指有权访问另外一个函数作用域中的变量的函数, MDN 对闭包的定义为:闭包是指那些能够访问自由变量的函数. (其中自由变量,指在函数中使 ...

  6. python闭包详解函数_Python闭包详解

    首先给出闭包函数的必要条件: 闭包函数必须返回一个函数对象 闭包函数返回的那个函数必须引用外部变量(一般不能是全局变量),而返回的那个函数内部不一定要return 几个典型的闭包例子: #ENV> ...

  7. 【Groovy】闭包 Closure ( 自定义闭包参数 | 自定义单个闭包参数 | 自定义多个闭包参数 | 闭包参数默认值指定 )

    文章目录 一.自定义闭包参数列表 1.定义一个自定义参数的闭包 2.定义多个自定义参数的闭包 3.为闭包参数指定默认值 二.完整代码示例 一.自定义闭包参数列表 如果要向 闭包 中 , 传递多个参数 ...

  8. php _invoke 闭包,PHP新特性之闭包、匿名函数

    闭包 闭包是什么? 1).闭包和匿名函数在PHP5.3中被引入. 2).闭包是指在创建时封装函数周围状态的函数,即使闭包所在的环境不存在了,闭包封装的状态依然存在,这一点和Javascript的闭包特 ...

  9. python闭包的应用场景_Python闭包函数定义与用法分析

    python函数的闭包怎么理解小编憎恨离别.但若,离别能让你牵挂,小编愿意离开你. 1. 闭包的概念 首先还得从基本概念说起,什么是闭包呢?来看下维基上的解释: 复制代码代码如下: 在计算机科学中,闭 ...

最新文章

  1. 基于Erlang语言的视频相似推荐系统 | 深度
  2. 数据挖掘如何分箱以及如何对每个箱子中的数据进行平滑处理
  3. Activity的setContentView的流程
  4. Eclipse 启动问题:'Initilizing Java Tooling' has encountered a problem(。。。)
  5. 携程在线风控系统架构
  6. centos7开启vnc服务_Centos7 VNC远程桌面服务安装配置
  7. 二叉树的二叉链表存储结构构建以及先序遍历
  8. [Qt教程] 第24篇 数据库(四)SQL查询模型QSqlQueryModel
  9. leetcode049. 最后一块石头的重量 II
  10. 三、Unity中的鼠标、键盘的获取
  11. 软件用户体验非常好的前端设计
  12. 信息学奥赛一本通 1016:整型数据类型存储空间大小 | OpenJudge NOI 1.2 01
  13. java知识点八:时间日期类
  14. java rfid 写入_RFID读写器函数JAVA调用示例
  15. Java URLDecoder和URLEncoder
  16. 转载“用USBOOT制作DOS启动盘”
  17. Windows:Win10 Dell笔记本禁用触摸板
  18. 阻止计算机访问注册表,电脑中毒了,注册表打不开了,提示注册表已被管理员禁止,这该怎么办...
  19. 作业07-Java GUI编程
  20. Java根据当前第几周获取周一和周日的日期方法

热门文章

  1. 计算机键盘输入法基础知识,电脑打字入门基础知识
  2. C语言768kb未压缩图片,若一幅图像的量化字长为16位,分辨率为800*600,它不经压缩占用的存储容量是()字节。A.690000B.1 - 试题答案网问答...
  3. Java字符串格式化详解
  4. VLookup怎么用详细步骤?VLookup函数的使用方法及实例
  5. Ubuntu 开机显示 initramfs 进不了系统
  6. 【Git版本控制管理】Gitee(码云)和GitHub的使用
  7. cloud云技术简介
  8. 其他网页可以使用,但百度首页打不开,百度搜索无法使用,怎么办
  9. Java选择题(十八)
  10. arm芯片,远程空中升级程序技术方案