javascript闭包的使用之按钮切换功能


Posted in Javascript onAugust 30, 2018

闭包实现按钮状态切换

看下面的代码:

var toggleBtn = document.getElementById('toggle');
var toggleFun = (function() {
 var checked = true;
 return function() {
  var color = checked ? 'red' : 'white';
  toggleBtn.style.backgroundColor = color;
  checked = !checked;
 };
})();
// 切换按钮
toggleBtn.addEventListener('click', toggleFun);

解释

上面的代码实现了点击按钮切换样式的功能,它用到了js的闭包特性。简单解释下:

toggleFun为一个立即执行函数,执行后toggleFun被赋值为内部函数:

toggleFun = function() {
   color = checked ? 'red' : 'white';
   toggleBtn.style.backgroundColor = color;
   checked = !checked;
 }

这个函数用到了外部函数的checked变量,这也是checked变量在立即执行函数执行完成后未被销毁的原因,因为还有其他地方用到了它。那么这个内部函数被用作事件监听器的回调函数,每点击一次就会被调用一次,从而可以通过更改checked的值来实现按钮切换效果。立即执行函数内的函数被全局下的toggleFun变量引用了,这就创建了一个闭包。

简而言之,闭包的作用就是在立即执行函数执行完并返回后,使得javascript的垃圾回收机制不会收回立即函数所占用的资源,因为立即执行函数的内部函数依赖立即执行函数中的变量。

额,上面写的太??铝耍?旅姘汛?肷晕⒏南拢?有┳⑹途突岣?忧逦??/p>

var toggleBtn = document.getElementById('toggle');
var outerFun = function() {
 var checked = true;
 // innerFun声明时用到了outerFun的局部变量
 var innerFun = function() {
  var color = checked ? 'red' : 'white';
  toggleBtn.style.backgroundColor = color;
  checked = !checked;
 };
 return innerFun;
};
var toggleFun = outerFun(); // toggleFun指向innerFun
// 切换按钮,每次点击都会调用innerFun
toggleBtn.addEventListener('click', toggleFun);

不用闭包,用全局变量

其实不用闭包也能实现按钮切换,不过就得用到全局变量来存储按钮状态:

var toggleBtn = document.getElementById('toggle');
var checked = true; // 全局变量存储按钮状态
var toggleFun = function() {
 var color = checked ? 'red' : 'white';
 toggleBtn.style.backgroundColor = color;
 checked = !checked;
};
toggleBtn.addEventListener('click', toggleFun);

但全局变量用多了会不好维护,代码不好控制。

补充:JavaScript闭包的概念及用法

1.闭包的概念: 

 闭包就是能够读取其他函数内部变量的函数.

 例如:  

function f1(){

var n=999;


function f2(){



alert(n); 


}


return f2;

}

var result=f1();

result(); // 999

 其中f2函数就是闭包。

 由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,

 因此可以把闭包简单理解成"定义在一个函数内部的函数"。

 所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

2.闭包的用途:

 闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,

 另一个就是让这些变量的值始终保持在内存中。

 怎么来理解这句话呢?请看下面的代码。

function f1(){


var n=999;


nAdd=function(){n+=1}


function f2(){



alert(n);


}


return f2;

}

var result=f1();

result(); // 999

nAdd();

result(); // 1000

 在这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,

 第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。

 为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,

 而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

 这段代码中另一个值得注意的地方,就是"nAdd=function(){n+=1}"这一行,

 首先在nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量。

 其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,

 所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。

总结

以上所述是小编给大家介绍的javascript闭包的使用之按钮切换功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
你可能不再需要JQUERY
Mar 09 Javascript
jQuery 判断元素上是否绑定了事件
Oct 28 Javascript
javascript 动态调整图片尺寸实现代码
Dec 28 Javascript
深入理解JavaScript定时机制
Oct 29 Javascript
javascript的console.log()用法小结
May 31 Javascript
jquery实现checkbox全选全不选的简单实例
Dec 31 Javascript
jquery实现的树形目录实例
Jun 26 Javascript
JS基于递归算法实现1,2,3,4,5,6,7,8,9倒序放入数组中的方法
Jan 03 Javascript
Vue使用vux-ui自定义表单验证遇到的问题及解决方法
May 10 Javascript
antd Upload 文件上传的示例代码
Dec 14 Javascript
Node 模块原理与用法详解
May 13 Javascript
js作用域及作用域链工作引擎
Jul 07 Javascript
Vue.set() this.$set()引发的视图更新思考及注意事项
Aug 30 #Javascript
基于Angularjs-router动态改变Title值的问题
Aug 30 #Javascript
从vue源码解析Vue.set()和this.$set()
Aug 30 #Javascript
vue-router动态设置页面title的实例讲解
Aug 30 #Javascript
解决vue select当前value没有更新到vue对象属性的问题
Aug 30 #Javascript
微信小程序使用wxParse解析html的实现示例
Aug 30 #Javascript
vue中rem的配置的方法示例
Aug 30 #Javascript
You might like
php实现分页工具类分享
2014/01/09 PHP
PHP的中使用非缓冲模式查询数据库的方法
2017/02/05 PHP
PHP实现对xml进行简单的增删改查(CRUD)操作示例
2017/05/19 PHP
根据分辩率调用不同的CSS.
2007/01/08 Javascript
jQuery JSON的解析方式分享
2011/04/05 Javascript
js日期时间补零的小例子
2013/03/05 Javascript
JQuery分屏指示器图片轮换效果实例
2015/05/21 Javascript
JavaScript制作简单的日历效果
2016/03/10 Javascript
JS闭包、作用域链、垃圾回收、内存泄露相关知识小结
2016/05/16 Javascript
javascript时间戳和日期字符串相互转换代码(超简单)
2016/06/22 Javascript
微信小程序开发之录音机 音频播放 动画实例 (真机可用)
2016/12/08 Javascript
js实现一个可以兼容PC端和移动端的div拖动效果实例
2016/12/09 Javascript
基于vue实现分页/翻页组件paginator示例
2017/03/09 Javascript
用react-redux实现react组件之间数据共享的方法
2018/06/08 Javascript
vue-cli3.0配置及使用注意事项详解
2018/09/05 Javascript
Vue props 单向数据流的实现
2018/11/06 Javascript
Vue 权限控制的两种方法(路由验证)
2019/08/16 Javascript
Elasticsearch实现复合查询高亮结果功能
2019/09/10 Javascript
js、jquery实现列表模糊搜索功能过程解析
2020/03/27 jQuery
vue-cli脚手架的.babelrc文件用法说明
2020/09/11 Javascript
[48:38]DOTA2亚洲邀请赛 3.31 小组赛 B组 Mineski vs Secret
2018/03/31 DOTA
django 连接数据库 sqlite的例子
2019/08/14 Python
Python3.7安装keras和TensorFlow的教程图解
2020/06/18 Python
Python如何用filter函数筛选数据
2020/03/05 Python
Django在Model保存前记录日志实例
2020/05/14 Python
Django获取model中的字段名和字段的verbose_name方式
2020/05/19 Python
html5 css3 动态气泡按钮实例演示
2012/12/02 HTML / CSS
小狗电器官方商城:中国高端吸尘器品牌
2017/03/29 全球购物
巴基斯坦电子产品购物网站:Home Shopping
2017/09/14 全球购物
捷克家电和家具购物网站:OKAY.cz
2020/07/23 全球购物
乡镇综治宣传月活动总结
2014/07/02 职场文书
社区领导班子四风问题原因分析及整改措施
2014/09/28 职场文书
教师党员学习十八届四中全会思想汇报
2014/11/03 职场文书
幼儿园教师师德师风承诺书
2015/04/28 职场文书
导游词之河姆渡遗址博物馆
2019/10/10 职场文书
详解Java ES多节点任务的高效分发与收集实现
2021/06/30 Java/Android