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 相关文章推荐
MSN消息提示类
Sep 05 Javascript
js 动态添加标签(新增一行,其实很简单,就是几个函数的应用)
Mar 26 Javascript
jquery判断单个复选框是否被选中的代码
Sep 03 Javascript
JS验证input输入框(字母,数字,符号,中文)
Mar 23 Javascript
ES6中数组array新增方法实例总结
Nov 07 Javascript
Vue导出json数据到Excel电子表格的示例
Dec 04 Javascript
详解node Async/Await 更好的异步编程解决方案
May 10 Javascript
JS实现简单的抽奖转盘效果示例
Feb 16 Javascript
JavaScript使用小插件实现倒计时的方法讲解
Mar 11 Javascript
JS实现的字符串数组去重功能小结
Jun 17 Javascript
详解Vue slot插槽
Nov 20 Vue.js
js 实现验证码输入框示例详解
Sep 23 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利用iframe实现无刷新文件上传功能的代码
2011/09/29 PHP
Laravel 4 初级教程之安装及入门
2014/10/30 PHP
PHP中UNIX时间戳和日期间的转换与计算实例
2014/11/19 PHP
Laravel中基于Artisan View扩展包创建及删除应用视图文件的方法
2016/10/08 PHP
Laravel接收前端ajax传来的数据的实例代码
2017/07/20 PHP
PHP实现的数据对象映射模式详解
2019/03/20 PHP
用PHP做了一个领取优惠券活动的示例代码
2019/07/05 PHP
laravel高级的Join语法详解以及使用Join多个条件
2019/10/16 PHP
js实现文本框输入文字个数限制代码
2015/12/25 Javascript
bootstrap table插件的分页与checkbox使用详解
2017/07/23 Javascript
nodeJS模块简单用法示例
2018/04/21 NodeJs
webpack4.x开发环境配置详解
2018/08/04 Javascript
浅谈开发eslint规则
2018/10/01 Javascript
Electron-vue开发的客户端支付收款工具的实现
2019/05/24 Javascript
[01:20]DOTA2 齐天大圣至宝动态展示
2016/12/13 DOTA
Python获取当前页面内所有链接的四种方法对比分析
2017/08/19 Python
python 解决动态的定义变量名,并给其赋值的方法(大数据处理)
2018/11/10 Python
浅谈python下tiff图像的读取和保存方法
2018/12/04 Python
python实现输入任意一个大写字母生成金字塔的示例
2019/10/27 Python
基于Tensorflow批量数据的输入实现方式
2020/02/05 Python
python def 定义函数,调用函数方式
2020/06/02 Python
Python 远程开关机的方法
2020/11/18 Python
利用Python过滤相似文本的简单方法示例
2021/02/03 Python
深入浅析CSS3中的Flex布局整理
2020/04/27 HTML / CSS
香港迪士尼乐园酒店预订:Hong Kong Disneyland Hotels
2017/05/02 全球购物
极简鞋类,赤脚的感觉:Lems Shoes
2019/08/06 全球购物
专业毕业生个性的自我评价
2013/10/03 职场文书
生产部管理制度
2014/01/31 职场文书
保密工作实施方案
2014/02/24 职场文书
员工廉洁自律承诺书
2014/05/26 职场文书
图书室标语
2014/06/21 职场文书
晚会主持人开场白台词
2015/05/28 职场文书
2015年中秋晚会主持稿
2015/07/30 职场文书
matlab xlabel位置的设置方式
2021/05/21 Python
基于HTML十秒做出淘宝页面
2021/10/24 HTML / CSS
Grafana可视化监控系统结合SpringBoot使用
2022/04/19 Redis