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 相关文章推荐
一个简单的javascript类定义例子
Sep 12 Javascript
js跨域问题之跨域iframe自适应大小实现代码
Jul 17 Javascript
javascript跑马灯悬停放大效果实现代码
Dec 12 Javascript
JavaScript对象创建及继承原理实例解剖
Feb 28 Javascript
页面使用密码保护代码
Apr 10 Javascript
javascript 将共享属性迁移到原型中去的实现方法
Aug 31 Javascript
Vue按需加载的具体实现
Dec 02 Javascript
JavaScript引用类型RegExp基本用法详解
Aug 09 Javascript
JS实现数组的增删改查操作示例
Aug 29 Javascript
详解关于Angular4 ng-zorro使用过程中遇到的问题
Dec 05 Javascript
vue读取本地的excel文件并显示在网页上方法示例
May 29 Javascript
jquery ui 实现 tab标签功能示例【测试可用】
Jul 25 jQuery
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
纯真IP数据库的应用 IP地址转化成十进制
2009/06/14 PHP
php下过滤html代码的函数 提高程序安全性
2010/03/02 PHP
THINKPHP支持YAML配置文件的设置方法
2015/03/17 PHP
深入浅出讲解:php的socket通信原理
2016/12/03 PHP
浅析PHP数据导出知识点
2018/02/17 PHP
js播放wav文件(源码)
2013/04/22 Javascript
阻止子元素继承父元素事件具体思路及实现
2013/05/02 Javascript
多选列表框动态添加,移动,删除,全选等操作的简单实例
2014/01/13 Javascript
js实现页面跳转重定向的几种方式
2014/05/29 Javascript
html的DOM中document对象forms集合用法实例
2015/01/21 Javascript
MVVM模式中ViewModel和View、Model有什么区别?
2015/06/19 Javascript
jQuery版本升级踩坑大全
2016/01/12 Javascript
Java框架SSH结合Easyui控件实现省市县三级联动示例解析
2016/06/12 Javascript
利用JavaScript判断浏览器类型及版本
2016/08/23 Javascript
Vuejs 组件——props数据传递的实例代码
2017/03/07 Javascript
d3.js实现立体柱图的方法详解
2017/04/28 Javascript
vue-music 使用better-scroll遇到轮播图不能自动轮播问题
2018/12/03 Javascript
H5实现手机拍照和选择上传功能
2019/12/18 Javascript
原生js实现照片墙效果
2020/10/13 Javascript
vue项目实现减少app.js和vender.js的体积操作
2020/11/12 Javascript
javascript实现随机抽奖功能
2020/12/30 Javascript
使用python编写脚本获取手机当前应用apk的信息
2014/07/21 Python
python取代netcat过程分析
2018/02/10 Python
win10 64bit下python NLTK安装教程
2018/09/19 Python
Django框架 信号调度原理解析
2019/09/04 Python
Python pandas.DataFrame 找出有空值的行
2019/09/09 Python
Python3实现将一维数组按标准长度分隔为二维数组
2019/11/29 Python
详解使用python爬取抖音app视频(appium可以操控手机)
2021/01/26 Python
浅谈Html5页面打开app的一些思考
2020/03/30 HTML / CSS
中国最大隐形眼镜网上商城:视客眼镜网
2016/10/30 全球购物
网页美工求职信
2014/02/15 职场文书
老师的检讨书
2014/02/23 职场文书
广告设计应届生求职信
2014/03/01 职场文书
《彩色世界》教学反思
2014/04/12 职场文书
2014年社区工作总结
2014/11/18 职场文书
收费员岗位职责
2015/02/14 职场文书