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 相关文章推荐
javascript 放大镜 v1.0 基于Yui2 实现的放大镜效果
Mar 08 Javascript
JS DOM 操作实现代码
Aug 01 Javascript
onkeypress字符按键兼容所有浏览器使用介绍
Apr 24 Javascript
sliderToggle在写jquery的计时器setTimeouter中不生效
May 26 Javascript
js表单登陆验证示例
Oct 19 Javascript
vue事件修饰符和按键修饰符用法总结
Jul 25 Javascript
浅析JS抽象工厂模式
Dec 14 Javascript
zTree 树插件实现全国五级地区点击后加载的示例
Feb 05 Javascript
Vue实现远程获取路由与页面刷新导致404错误的解决
Jan 31 Javascript
JS实现可用滑块滑动的缓动图代码
Sep 01 Javascript
微信小程序自定义联系人弹窗
May 26 Javascript
js实现飞机大战游戏
Aug 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
PHP 和 MySQL 基础教程(四)
2006/10/09 PHP
PHP 配置open_basedir 让各虚拟站点独立运行
2009/11/12 PHP
php实现修改新闻时删除图片的方法
2015/05/12 PHP
Javascript调用C#代码
2011/01/17 Javascript
Extjs 继承Ext.data.Store不起作用原因分析及解决
2013/04/15 Javascript
jquery给图片添加鼠标经过时的边框效果
2013/11/12 Javascript
toggle()隐藏问题的解决方法
2014/02/17 Javascript
JqueryMobile动态生成listView并实现刷新的两种方法
2014/03/05 Javascript
jQuery Migrate 1.1.0 Released 注意事项
2014/06/14 Javascript
JS中的Replace方法使用经验分享
2015/05/20 Javascript
jquery表单验证需要做些什么
2015/11/17 Javascript
JS中正则表达式只有3种匹配模式(没有单行模式)详解
2016/07/28 Javascript
jquery html5 视频播放控制代码
2016/11/06 Javascript
JavaScript利用正则表达式替换字符串中的内容
2016/12/12 Javascript
Vuejs入门教程之Vue生命周期,数据,手动挂载,指令,过滤器
2017/04/19 Javascript
你不知道的Vue技巧之--开发一个可以通过方法调用的组件(推荐)
2019/04/15 Javascript
vue实现菜单切换功能
2019/05/08 Javascript
js模拟F11页面全屏显示
2019/09/17 Javascript
createObjectURL方法实现本地图片预览
2019/09/30 Javascript
微信小程序静默登录的实现代码
2020/01/08 Javascript
python实现用于测试网站访问速率的方法
2015/05/26 Python
Python实例一个类背后发生了什么
2016/02/09 Python
python 循环while和for in简单实例
2016/08/16 Python
python实现遍历文件夹修改文件后缀
2018/08/28 Python
PIL对上传到Django的图片进行处理并保存的实例
2019/08/07 Python
Python解释器以及PyCharm的安装教程图文详解
2020/02/26 Python
Python gevent协程切换实现详解
2020/09/14 Python
python常量折叠基础知识点讲解
2021/02/28 Python
CSS3中伪元素::before和::after的用法示例
2017/09/18 HTML / CSS
REISS美国官网:伦敦最受欢迎的时尚品牌
2019/08/16 全球购物
思想品德课教学反思
2014/02/10 职场文书
建筑工地门卫岗位职责
2014/04/30 职场文书
拓展策划方案
2014/06/03 职场文书
个人工作作风整改措施思想汇报
2014/10/13 职场文书
2014年妇女工作总结
2014/12/06 职场文书
Win11安装受阻怎么办? Windows11安装问题与解决方案汇总
2021/11/21 数码科技