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 js 重置表单 reset()具体实现代码
Aug 05 Javascript
一个Action如何调用两个不同的方法
May 22 Javascript
用JavaScript实现用一个DIV来包装文本元素节点
Sep 09 Javascript
一道JS前端闭包面试题解析
Dec 25 Javascript
在Node.js中使用Javascript Generators详解
May 05 Javascript
深入解析桶排序算法及Node.js上JavaScript的代码实现
Jul 06 Javascript
js判断数组key是否存在(不用循环)的简单实例
Aug 03 Javascript
Vue Router去掉url中默认的锚点#
Aug 01 Javascript
Vue+Node实现商品列表的分页、排序、筛选,添加购物车功能详解
Dec 07 Javascript
原生js实现的观察者和订阅者模式简单示例
Apr 18 Javascript
vue 通过 Prop 向子组件传递数据的实现方法
Oct 30 Javascript
微信小程序实现倒计时功能
Nov 19 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跨服务器访问方法小结
2015/05/12 PHP
Yii1.1中通过Sql查询进行的分页操作方法
2017/03/16 PHP
js 面向对象的技术创建高级 Web 应用程序
2010/02/25 Javascript
url地址自动加#号问题说明
2010/08/21 Javascript
基于JQuery的多标签实现代码
2012/09/19 Javascript
关于在IE下的一个安全BUG --可用于跟踪用户的系统鼠标位置
2013/04/17 Javascript
JS动态添加与删除select中的Option对象(示例代码)
2013/12/25 Javascript
window.onload与$(document).ready()的区别分析
2015/05/30 Javascript
jquery实现在网页指定区域显示自定义右键菜单效果
2015/08/25 Javascript
深入解析JavaScript中的立即执行函数
2016/05/21 Javascript
关于Javascript回调函数的一个妙用
2016/08/29 Javascript
JavaScript中创建对象的7种模式详解
2017/02/21 Javascript
Angular 4中如何显示内容的CSS样式示例代码
2017/11/06 Javascript
vue项目使用微信公众号支付总结及遇到的坑
2018/10/23 Javascript
vue的.vue文件是怎么run起来的(vue-loader)
2018/12/10 Javascript
详解Vue-cli3.X使用px2rem遇到的问题
2019/08/09 Javascript
vue+elementUI 实现内容区域高度自适应的示例
2020/09/26 Javascript
如何使用RoughViz可视化Vue.js中的草绘图表
2021/01/30 Vue.js
Python中实现参数类型检查的简单方法
2015/04/21 Python
Windows下Python2与Python3两个版本共存的方法详解
2017/02/12 Python
如何爬取通过ajax加载数据的网站
2019/08/15 Python
什么是python的必选参数
2020/06/21 Python
python 读取.nii格式图像实例
2020/07/01 Python
Python使用tkinter实现小时钟效果
2021/02/22 Python
男女时尚与复古风格在线购物:RoseGal(全球免费送货)
2017/07/19 全球购物
英国发展最快的在线超市之一:Click Marketplace
2021/02/15 全球购物
七年级历史教学反思
2014/02/05 职场文书
《灯光》教学反思
2014/02/08 职场文书
《珍珠泉》教学反思
2014/02/20 职场文书
私人委托书格式
2014/09/10 职场文书
不服从上级领导安排的检讨书
2014/09/14 职场文书
2014客服代表实习自我鉴定
2014/09/18 职场文书
国博复兴之路观后感
2015/06/02 职场文书
火烧圆明园的观后感
2015/06/03 职场文书
党员反邪教心得体会
2016/01/15 职场文书
《游戏公平》教学反思
2016/02/20 职场文书