JavaScript 闭包的使用场景


Posted in Javascript onSeptember 17, 2020

一、闭包

由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,闭包就是能够读取其他函数内部变量的函数。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

比如下面的代码:

function f1() {
 var n = 999;
 function f2() {
 console.log(n);
 }
 return f2;
}
var result = f1();
result();//999

函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1就是不可见的。

这就是Javascript语言特有的"链式作用域"结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,就可以在f1外部读取它的内部变量了。

二、闭包的使用场景

1.setTimeout

原生的setTimeout传递的第一个函数不能带参数,通过闭包可以实现传参效果。

function f1(a) {
 function f2() {
  console.log(a);
 }
 return f2;
}
var fun = f1(1);
setTimeout(fun,1000);//一秒之后打印出1

2.回调

定义行为,然后把它关联到某个用户事件上(点击或者按键)。代码通常会作为一个回调(事件触发时调用的函数)绑定到事件。

比如下面这段代码:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>测试</title>
</head>
<body>
 <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="size-12">12</a>
 <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="size-20">20</a>
 <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="size-30">30</a>

 <script type="text/javascript">
  function changeSize(size){
   return function(){
    document.body.style.fontSize = size + 'px';
   };
  }

  var size12 = changeSize(12);
  var size14 = changeSize(20);
  var size16 = changeSize(30);

  document.getElementById('size-12').onclick = size12;
  document.getElementById('size-20').onclick = size14;
  document.getElementById('size-30').onclick = size16;

 </script>
</body>
</html>

当点击数字时,字体也会变成相应的大小。

3.函数防抖

在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。

实现的关键就在于setTimeOut这个函数,由于还需要一个变量来保存计时,考虑维护全局纯净,可以借助闭包来实现。

如下代码所示:

/*
* fn [function] 需要防抖的函数
* delay [number] 毫秒,防抖期限值
*/
function debounce(fn,delay){
 let timer = null //借助闭包
 return function() {
  if(timer){
   clearTimeout(timer) //进入该分支语句,说明当前正在一个计时过程中,并且又触发了相同事件。所以要取消当前的计时,重新开始计时
   timer = setTimeOut(fn,delay) 
  }else{
   timer = setTimeOut(fn,delay) // 进入该分支说明当前并没有在计时,那么就开始一个计时
  }
 }
}

4.封装私有变量

如下面代码:用js创建一个计数器

方法1:

function f1() {
 var sum = 0;
 var obj = {
  inc:function () {
   sum++;
   return sum;
  }
};
 return obj;
}
let result = f1();
console.log(result.inc());//1
console.log(result.inc());//2
console.log(result.inc());//3

在返回的对象中,实现了一个闭包,该闭包携带了局部变量x,并且,从外部代码根本无法访问到变量x。

方法2:

function f1() {
 var sum = 0;
 function f2() {
  sum++;
  return f2;
 }
 f2.valueOf = function () {
  return sum;
 };
 f2.toString = function () {
  return sum+'';
 };
 return f2;
}
//执行函数f1,返回的是函数f2
console.log(+f1());//0
console.log(+f1()())//1
console.log(+f1()()())//2

所有js数据类型都拥有valueOf和toString这两个方法,null除外
valueOf()方法:返回指定对象的原始值。
toString()方法:返回对象的字符串表示。
在数值运算中,优先调用了valueOf,字符串运算中,优先调用toString
sum+' '是一个字符串类型的数据

以上就是JavaScript 闭包的使用场景的详细内容,更多关于JavaScript 闭包的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
控制打印时页眉角的代码
Feb 08 Javascript
jquery下实现overlay遮罩层代码
Aug 25 Javascript
jQuery中[attribute!=value]选择器用法实例
Dec 31 Javascript
js钢琴按钮波浪式图片排列效果代码分享
Aug 26 Javascript
javascript判断元素存在和判断元素存在于实时的dom中的方法
Jan 17 Javascript
js 数字、字符串、布尔值的转换方法(必看)
Apr 07 Javascript
jquery.masonry瀑布流效果
May 25 jQuery
ionic中的$ionicPlatform.ready事件中的通用设置
Jun 11 Javascript
JS动态插入脚本和插入引用外部链接脚本的方法
May 21 Javascript
详解浏览器缓存和webpack缓存配置
Jul 06 Javascript
微信小程序实现笑脸评分功能
Nov 03 Javascript
ZK中使用JS读取客户端txt文件内容问题
Nov 07 Javascript
javascript贪吃蛇游戏设计与实现
Sep 17 #Javascript
js实现简单的随机点名器
Sep 17 #Javascript
谈谈JavaScript中的垃圾回收机制
Sep 17 #Javascript
js对象属性名驼峰式转下划线的实例代码
Sep 17 #Javascript
详细分析JavaScript中的深浅拷贝
Sep 17 #Javascript
js实现鼠标滑动到某个div禁止滚动
Sep 17 #Javascript
原生js+css实现tab切换功能
Sep 17 #Javascript
You might like
如何删除多级目录
2006/10/09 PHP
使用array_map简单搞定PHP删除文件、删除目录
2014/10/29 PHP
Prototype使用指南之array.js
2007/01/10 Javascript
关于JS字符串函数String.replace()
2013/04/07 Javascript
document.execCommand()的用法小结
2014/01/08 Javascript
javascript获得当前的信息的一些常用命令
2015/02/25 Javascript
AngularJS辅助库browserTrigger用法示例
2016/11/03 Javascript
bootstrap实现每隔5秒自动轮播效果
2016/12/20 Javascript
BootStrap selectpicker后台动态绑定数据
2017/06/01 Javascript
AngularJS中scope的绑定策略实例分析
2017/10/30 Javascript
解决node修改后需频繁手动重启的问题
2018/05/13 Javascript
jQuery 导航自动跟随滚动的实现代码
2018/05/30 jQuery
Vue+Mock.js模拟登录和表格的增删改查功能
2018/07/26 Javascript
JS返回页面时自动回滚到历史浏览位置
2018/09/26 Javascript
vue实现表单未编辑或未保存离开弹窗提示功能
2020/04/08 Javascript
three.js欧拉角和四元数的使用方法
2020/07/26 Javascript
[00:18]天涯墨客三技能展示
2018/08/25 DOTA
跟老齐学Python之关于类的初步认识
2014/10/11 Python
Python随手笔记第一篇(2)之初识列表和元组
2016/01/23 Python
python中使用正则表达式的连接符示例代码
2017/10/10 Python
python2.7安装图文教程
2018/03/13 Python
学python安装的软件总结
2019/10/12 Python
使用PyCharm进行远程开发和调试的实现
2019/11/04 Python
Python+Dlib+Opencv实现人脸采集并表情判别功能的代码
2020/07/01 Python
python 解决函数返回return的问题
2020/12/05 Python
萌新的HTML5 入门指南
2020/11/06 HTML / CSS
美国韩国化妆品和护肤品购物网站:Beautytap
2018/07/29 全球购物
英国在线潜水商店:Simply Scuba
2019/03/25 全球购物
委托与事件是什么关系?为什么要使用委托
2014/04/18 面试题
幼儿园国庆节活动方案
2014/02/01 职场文书
绿色城市实施方案
2014/03/19 职场文书
超越自我演讲稿
2014/05/21 职场文书
教师竞聘上岗演讲稿
2014/09/03 职场文书
思想作风整顿个人剖析材料
2014/10/06 职场文书
2015年公务员工作总结
2015/04/24 职场文书
公司客户答谢酒会祝酒词
2015/08/11 职场文书