JS闭包的作用与优缺点
一、什么是闭包
闭包是指一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)。
简单来说就是指有权访问另一个函数作用域中变量的函数。
举个例子:
function fn() {var num = 10;function fun() {console.log(num);}fun();
}
fn();
这就是一个闭包了。fun 这个函数作用域访问了另外一个函数 fn 里面的局部变量 num。
二、闭包作用
在js作用域环境中访问变量的权利是由内向外的,内部作用域可以获得当前作用域下的变量并且可以获得包含当前作用域的外层作用域下的变量,反之则不能,也就是说在外层作用域下无法获取内层作用域下的变量,同样在不同的函数作用域中也是不能相互访问彼此变量的,那么我们想在一个函数内部也有权限访问另一个函数内部的变量该怎么办呢?闭包就是用来解决这一需求的。
来看下面一个例子:
function fn() {var num = 10;function fun() {console.log(num);}fun();
}
fn();
一个简单地闭包。正常情况下我们无法在外面访问到num这个变量。但通过闭包我们就可以让fn 外面的作用域访问fn内部的局部变量。只需要这么写:
function fn() {var num = 10;function fun() {console.log(num);}return fun;//将fun函数当返回值返回
}
var f =fn();//接受这个返回值
上面代码执行时类似于(我说的是类似):
//类似于
var f = function() {console.log(num);
}
f();
返回的是函数,再调用函数,而这个函数在fn里面,这样就可以访问到里面的num了
所以说闭包的主要作用就是:延伸了变量的作用范围。
三、闭包的优缺点
举个简单地例子。实现点击li输出当前li的索引号时。
有时候就想当然了,不仔细思考犯这个错误(注意以下写法是错误的)
var lis = document.querySelector('ul').querySelectorAll('li');
for (var i = 0; i < lis.length; i++) {console.log(i);
}
因为for是同步任务,function是异步任务。所以最后输出的都是4。
因此正常书写利用动态添加属性的方式书写:
var lis = document.querySelector('ul').querySelectorAll('li');
for (var i = 0; i < lis.length; i++) {lis[i].index = i;lis[i].onclick = function () {console.log(this.index);}
}
利用闭包书写:
立即执行函数IIFE ()(); ,创建函数后就立即执行。
for (var i = 0; i < lis.length; i++) {(function (i) {lis[i].onclick = function () {console.log(i);}})(i);
}
利用for循环创建了4个立即执行函数。
这样看来其实还是第一种方法更简单些。并不是说闭包一定是好的。
利用闭包书写,每一次循环都创建了一个i,不点击就不会销毁,这样很占用内存,造成内存泄漏。这就是闭包的缺点。当然闭包也有自己的用处,在某些情况下,想延长变量的使用范围我们就可以使用闭包了。
总结:
优点:
①保护函数内的变量安全 ,实现封装,防止变量流入其他环境发生命名冲突
②在内存中维持一个变量,可以做缓存(但使用多了同时也是一项缺点,消耗内存)。
③匿名自执行函数可以减少内存消耗。(function(){}){}
坏处:
①被引用的私有变量不能被销毁,增大了内存消耗,造成内存泄漏,解决方法是可以在使用完变量后手动为它赋值为null。
②其次由于闭包涉及跨域访问,所以会导致性能损失,我们可以通过把跨作用域变量存储在局部变量中,然后直接访问局部变量,来减轻对执行速度的影响。
总的来说
闭包:函数内部包裹函数,作用域链得不到释放,造成消耗内存。
四、闭包的应用
闭包应用-计算打车价格
打车起步价13(3公里内), 之后每多一公里增加 5块钱. 用户输入公里数就可以计算打车价格,
如果有拥堵情况,总价格多收取10块钱拥堵费。
var car = (function () {var start = 13; // 起步价 局部变量var total = 0; // 总价 局部变量return {// 正常的总价price: function (n) { //n 公里数if (n <= 3) {total = start;} else {total = start + (n - 3) * 5}return total;},// 拥堵之后的费用yd: function (flag) {return flag ? total + 10 : total;}}
})();
console.log(car.price(5)); // 23
console.log(car.yd(true)); // 33console.log(car.price(1)); // 13
console.log(car.yd(false)); // 13
JS闭包的作用与优缺点相关推荐
- js闭包的应用和优缺点
闭包应用 封装一个具有特定功能的JS模块,将所有数据和功能封装在函数内部,只向外暴露指定的几个方法或者对象,使用者只需通过约定的方法来实现对应的功能. 下面来看代码 function NumOpera ...
- JS闭包及其作用(简单举例)
闭包:保证数据的安全,需要反复使用的时候采用闭包 查阅了很多资料,把闭包分为两类理解: 广义闭包:函数内部用到了外部变量 狭义闭包:内部函数用到了外部函数的局部变量 因为闭包是用来反复调用的安全数据, ...
- 面试官:谈谈对JS闭包的理解及常见应用场景(闭包的作用)
文章目录 对JS闭包的理解及常见应用场景(闭包的作用) 1.变量作用域 2.如何从外部读取函数内部的变量? 3.闭包概念 4.闭包用途 5.闭包的理解 6.闭包应用场景 setTimeout传参 回调 ...
- js 闭包作用(转自别人的)
Stone 2012-09-28 15:44 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言 ...
- js闭包的理解和作用
一.为什么引入闭包 JS为每个变量对象定了作用域,在ES5 中只有全局作用域和函数作用域,没有块级作用域,由内向外形成作用域链,函数外部不能访问函数内部作用域的局部变量.在实际开发中会带来很多不便. ...
- javascript深入理解js闭包[转]
一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...
- javascript深入理解js闭包
一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...
- 简单理解js闭包、类型引用....第一章
js 闭包函数.类型引用.this指向.对象原型链...这些东西让我们对js又爱又恨!js虐我千百遍,我待js如初恋. 很多初学者一开始会觉得这些概念没什么用,导致对这些东西产生一种抵抗力.接下来我们 ...
- 关于JS闭包,作者不详(转)
说明:本文由两篇文章结合而成,系从他人笔记中转过来的, 具体作者不详.因为觉得不错,遂共享之.如有侵权,立删致歉. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变 ...
最新文章
- 以太网端口类型和可插拔模块揭密
- egg.js java 生产数据_eggjs中,自动从数据库直接生成model.
- 第十四节:Lambda、linq、SQL的相爱相杀(3)
- 直通BAT必考题系列:7种JVM垃圾收集器特点,优劣势、及使用场景
- 半波对称振子方向图_第一讲 天线的方向图(下).pdf
- 组网胖模式_胖瘦AP组网优劣对比,你知道吗?
- java 实现复制_在java中如何实现复制,粘贴,剪切
- pygame 安装方法
- 官方授权正版老牌截图工具 Ashampoo Snap 12 中文网站 屏幕截图与视频录制工具
- 差分进化算法python_L单目标差分进化算法
- 2.4 PRINCE2
- 华为各系列交换机限速配置
- C语言之基本算法34—分解质因数(方法一)
- VR球类游戏填坑总结
- 第一行代码android网课,使用Mongodb实现打卡签到系统的实例代码
- C语言malloc与calloc区别
- 英语日常用语900句(5)
- 闯荡Linux帝国:nginx的创业故事
- 新增商品(商品维护模块)
- html5弹性盒子的作用,flexbox弹性盒子,真正意义上的布局样式