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实现表格增删改操作实例详解
May 15 Javascript
js和jQuery设置Opacity半透明 兼容IE6
May 24 Javascript
javascript实现图片左右滚动效果【可自动滚动,有左右按钮】
Sep 19 Javascript
微信小程序 页面跳转和数据传递实例详解
Jan 19 Javascript
关于vue-router路径计算问题
May 10 Javascript
使用JS中的Replace()方法遇到的问题小结
Oct 20 Javascript
详解性能更优越的小程序图片懒加载方式
Jul 18 Javascript
Layui数据表格之获取表格中所有的数据方法
Aug 20 Javascript
Vue 前端实现登陆拦截及axios 拦截器的使用
Jul 17 Javascript
jQuery 查找元素操作实例小结
Oct 02 jQuery
Vue数字输入框组件的使用方法
Oct 19 Javascript
深入理解javascript中的this
Feb 08 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变量作用域的一些问题
2013/08/08 PHP
discuz加密解密函数使用方法和中文注释
2014/01/21 PHP
地震发生中逃生十大法则
2008/05/12 Javascript
Jquery 表单取值赋值的一些基本操作
2009/10/11 Javascript
JavaScript 事件的一些重要说明
2009/10/25 Javascript
jQuery+jqmodal弹出窗口实现代码分明
2010/06/14 Javascript
jQuery 源码分析笔记(2) 变量列表
2011/05/28 Javascript
Javascript的严格模式strict mode详细介绍
2014/06/06 Javascript
AngularJS初始化静态模板详解
2016/01/14 Javascript
javascript简单写的判断电话号码实例
2017/05/24 Javascript
jQuery实现切换隐藏与显示同时切换图标功能
2017/10/29 jQuery
JS 验证码功能的三种实现方式
2018/11/26 Javascript
vue-router实现嵌套路由的讲解
2019/01/19 Javascript
JavaScript使用面向对象实现的拖拽功能详解
2019/06/12 Javascript
使用Vue-Awesome-Swiper实现旋转叠加轮播效果&amp;平移轮播效果
2019/08/16 Javascript
JS用最简单的方法实现四舍五入
2019/08/27 Javascript
Python实现将DOC文档转换为PDF的方法
2015/07/25 Python
Python中列表、字典、元组数据结构的简单学习笔记
2016/03/20 Python
Python爬虫基础之XPath语法与lxml库的用法详解
2018/09/13 Python
Python基于百度云文字识别API
2018/12/13 Python
六行python代码的爱心曲线详解
2019/05/17 Python
python中使用ctypes调用so传参设置遇到的问题及解决方法
2019/06/19 Python
关于pytorch中网络loss传播和参数更新的理解
2019/08/20 Python
Python列表的切片实例讲解
2019/08/20 Python
利用rest framework搭建Django API过程解析
2019/08/31 Python
python 内置函数汇总详解
2019/09/16 Python
pycharm如何使用anaconda中的各种包(操作步骤)
2020/07/31 Python
python修改微信和支付宝步数的示例代码
2020/10/12 Python
纯css3实现照片墙效果
2014/12/26 HTML / CSS
美国在线精品家居网站:Burke Decor
2017/04/12 全球购物
优秀的计算机专业求职信范文
2013/12/27 职场文书
巾帼建功标兵事迹材料
2014/05/11 职场文书
2015年采购工作总结
2015/04/10 职场文书
电影开国大典观后感
2015/06/04 职场文书
创新创业项目计划书该怎样写?
2019/08/13 职场文书
MySQL日期时间函数知识汇总
2022/03/17 MySQL