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 相关文章推荐
jQuery简单tab切换效果实现方法
Apr 08 Javascript
jquery移动端TAB触屏切换实现效果
Dec 22 Javascript
对象题目的一个坑 理解Javascript对象
Dec 22 Javascript
jQuery实现的可编辑表格完整实例
Jun 20 Javascript
jQuery实现左右滑动的toggle方法
Mar 03 jQuery
如何解决.vue文件url引用文件的问题
Jan 18 Javascript
Elasticsearch实现复合查询高亮结果功能
Sep 10 Javascript
vue使用swiper.js重叠轮播组建样式
Nov 14 Javascript
javascript实现点击星星小游戏
Dec 24 Javascript
微信公众号服务器验证Token步骤图解
Dec 30 Javascript
Javascript Worker子线程代码实例
Feb 20 Javascript
Vue 请求传公共参数的操作
Jul 31 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
从零开始学YII2框架(三)扩展插件yii2-gird
2014/08/20 PHP
php根据日期显示所在星座的方法
2015/07/13 PHP
jsvascript图像处理—(计算机视觉应用)图像金字塔
2013/01/15 Javascript
IE8对JS通过属性和数组遍历解析不一样的地方探讨
2013/05/06 Javascript
JavaScript检测弹出窗口是否已经关闭的方法
2015/03/24 Javascript
js实现Select头像选择实时预览代码
2015/08/17 Javascript
JavaScript实现的Tween算法及缓冲特效实例代码
2015/11/03 Javascript
微信小程序 Flex布局详解
2016/10/09 Javascript
AngularJS表格添加序号的方法
2017/03/03 Javascript
Angular项目中$scope.$apply()方法的使用详解
2017/07/26 Javascript
浅谈Vue路由快照实现思路及其问题
2018/06/07 Javascript
解决vue热替换失效的根本原因
2018/09/19 Javascript
AJAX在JQuery中的应用详解
2019/01/30 jQuery
微信小程序人脸识别功能代码实例
2019/05/07 Javascript
pageGroup.js实现分页功能
2019/07/27 Javascript
使用layui的layer组件做弹出层的例子
2019/09/27 Javascript
vue 将多个过滤器封装到一个文件中的代码详解
2020/09/05 Javascript
Python中删除文件的程序代码
2011/03/13 Python
Python 元组(Tuple)操作详解
2014/03/11 Python
使用Python的Tornado框架实现一个一对一聊天的程序
2015/04/25 Python
在Python中使用matplotlib模块绘制数据图的示例
2015/05/04 Python
centos6.8安装python3.7无法import _ssl的解决方法
2018/09/17 Python
Python 画出来六维图
2019/07/26 Python
python实现文字版扫雷
2020/04/24 Python
详解pytorch中squeeze()和unsqueeze()函数介绍
2020/09/03 Python
利用python制作拼图小游戏的全过程
2020/12/04 Python
Tiqets荷兰:出售欧洲最美丽的景点和博物馆门票
2018/01/09 全球购物
如何实现jdbc性能优化
2012/07/30 面试题
经典c++面试题三
2015/07/08 面试题
《学会待客》教学反思
2014/02/22 职场文书
电大毕业生自我鉴定
2014/04/10 职场文书
林肯就职演讲稿
2014/05/19 职场文书
高一军训决心书
2015/02/05 职场文书
2015暑期社会实践通讯稿
2015/07/18 职场文书
goland 清除所有的默认设置操作
2021/04/28 Golang
Java GUI编程菜单组件实例详解
2022/04/07 Java/Android