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 相关文章推荐
Prototype使用指南之range.js
Jan 10 Javascript
jquery tools 系列 scrollable学习
Sep 06 Javascript
jquery任意位置浮动固定层插件用法实例
May 29 Javascript
JavaScript来实现打开链接页面的简单实例
Jun 02 Javascript
Javascript之String对象详解
Jun 08 Javascript
jQuery+CSS3文字跑马灯特效的简单实现
Jun 25 Javascript
JavaScript中获取时间的函数集
Aug 16 Javascript
使用ionic切换页面卡顿的解决方法
Dec 16 Javascript
利用three.js画一个3D立体的正方体示例代码
Nov 19 Javascript
Redux实现组合计数器的示例代码
Jul 04 Javascript
使用Vue开发自己的Chrome扩展程序过程详解
Jun 21 Javascript
通过javascript实现段落的收缩与展开
Jun 26 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
使用CodeIgniter的类库做图片上传
2014/06/12 PHP
php中青蛙跳台阶的问题解决方法
2018/10/14 PHP
CSS JavaScript 实现菜单功能 改进版
2008/12/09 Javascript
如何实现textarea里的不同文本显示不同颜色
2014/01/20 Javascript
jQuery实现动画效果的简单实例
2014/01/27 Javascript
javascript Deferred和递归次数限制实例
2014/10/21 Javascript
JQuery用户名校验的具体实现
2016/03/18 Javascript
阻止表单提交按钮多次提交的完美解决方法
2016/05/16 Javascript
JQuery 设置checkbox值二次无效的解决方法
2016/07/22 Javascript
React实现双向绑定示例代码
2016/09/19 Javascript
AngularJS中指令的四种基本形式实例分析
2016/11/22 Javascript
Nodejs 获取时间加手机标识的32位标识实现代码
2017/03/07 NodeJs
js判断PC端与移动端跳转
2020/12/24 Javascript
JS运动特效之任意值添加运动的方法分析
2018/01/24 Javascript
使用Vue的slot插槽分发父组件内容实现高度复用、更加灵活的组件(推荐)
2018/05/01 Javascript
JavaScript生成指定范围随机数和随机序列的方法
2018/05/05 Javascript
原生JS实现手动轮播图效果实例代码
2018/11/22 Javascript
jQuery实现表格的增、删、改操作示例
2019/01/27 jQuery
一文了解vue-router之hash模式和history模式
2019/05/31 Javascript
微信小程序发布新版本时自动提示用户更新的方法
2019/06/07 Javascript
Vue2.X和Vue3.0数据响应原理变化的区别
2019/11/07 Javascript
vue实现简易的双向数据绑定
2020/12/29 Vue.js
JavaScript canvas实现雨滴特效
2021/01/10 Javascript
python实现自动登录人人网并访问最近来访者实例
2014/09/26 Python
Python语言描述KNN算法与Kd树
2017/12/13 Python
python 中值滤波,椒盐去噪,图片增强实例
2019/12/18 Python
Python 使用 prettytable 库打印表格美化输出功能
2019/12/26 Python
Python利用Xpath选择器爬取京东网商品信息
2020/06/01 Python
TobyDeals美国:在电子产品上获得最好的优惠和折扣
2019/08/11 全球购物
应付会计岗位职责
2013/12/12 职场文书
餐饮业经理竞聘演讲稿
2014/01/14 职场文书
咖啡馆创业计划书
2014/01/26 职场文书
社区党建工作方案
2014/06/10 职场文书
2015秋季幼儿园开学寄语
2015/03/25 职场文书
2015年高中班级工作总结
2015/07/21 职场文书
Android Flutter实现图片滑动切换效果
2022/04/07 Java/Android