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 相关文章推荐
分享几个超级震憾的图片特效
Jan 08 Javascript
javascript使用定时函数实现跳转到某个页面
Dec 25 Javascript
jquery常用方法及使用示例汇总
Nov 08 Javascript
JS模拟Dialog弹出浮动框效果代码
Oct 16 Javascript
谈谈我对JavaScript中typeof和instanceof的深入理解
Dec 25 Javascript
Web前端框架bootstrap实战【第一次接触使用】
Dec 28 Javascript
node中间层实现文件上传功能
Jun 11 Javascript
jQuery的ztree仿windows文件新建和拖拽功能的实现代码
Dec 05 jQuery
使用Vue-Awesome-Swiper实现旋转叠加轮播效果&amp;平移轮播效果
Aug 16 Javascript
微信小程序实现音频文件播放进度的实例代码
Mar 02 Javascript
PHP 502bad gateway原因及解决方案
Nov 13 Javascript
AJAX实现指定部分页面刷新效果
Oct 16 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
PHP操作数组的一些函数整理介绍
2011/07/17 PHP
为百度UE编辑器上传图片添加水印功能
2015/04/16 PHP
php文件缓存类用法实例分析
2015/04/22 PHP
jQuery中filter(),not(),split()使用方法
2010/07/06 Javascript
Javascript跨域请求的4种解决方式
2013/03/17 Javascript
js单词形式的运算符
2014/05/06 Javascript
fixedBox固定div漂浮代码支持ie6以上大部分主流浏览器
2014/06/26 Javascript
javascript数据结构之双链表插入排序实例详解
2015/11/25 Javascript
非常酷炫的Bootstrap图片轮播动画
2016/05/27 Javascript
js数组的五种迭代方法及两种归并方法(推荐)
2016/06/14 Javascript
Javascript打印局部页面实例
2016/06/21 Javascript
vue-cli webpack 引入jquery的方法
2018/01/10 jQuery
JavaScript基于遍历操作实现对象深拷贝功能示例
2019/03/05 Javascript
为什么Vue3.0使用Proxy实现数据监听(defineProperty表示不背这个锅)
2019/10/14 Javascript
vue 实现用户登录方式的切换功能
2020/04/14 Javascript
VueJS实现用户管理系统
2020/05/29 Javascript
python传递参数方式小结
2015/04/17 Python
python snownlp情感分析简易demo(分享)
2017/06/04 Python
Python编程实现两个文件夹里文件的对比功能示例【包含内容的对比】
2017/06/20 Python
快速查询Python文档方法分享
2017/12/27 Python
python入门前的第一课 python怎样入门
2018/03/06 Python
python 除法保留两位小数点的方法
2018/07/16 Python
pygame游戏之旅 游戏中添加显示文字
2018/11/20 Python
python实现处理mysql结果输出方式
2020/04/09 Python
澳大利亚宠物食品和药物在线:Jumbo Pets
2018/03/24 全球购物
Ootori在线按摩椅店:一家专业的按摩椅制造商
2019/04/10 全球购物
美国购买舞会礼服网站:Couture Candy
2019/12/29 全球购物
远程学习的教学用品和家庭学习资源:Really Good Stuff
2020/04/27 全球购物
巴西24小时在线药房:Drogasil
2020/06/20 全球购物
群众路线教育实践活动总结
2014/10/30 职场文书
教师党的群众路线教育实践活动学习心得体会
2014/10/30 职场文书
2015年八一建军节演讲稿
2015/03/19 职场文书
房地产项目合作意向书
2015/05/08 职场文书
《索溪峪的野》教学反思
2016/02/19 职场文书
2019年入党思想汇报格式与要求
2019/06/25 职场文书
MongoDB orm框架的注意事项及简单使用
2021/06/20 MongoDB