js 闭包深入理解与实例分析


Posted in Javascript onMarch 19, 2020

本文实例讲述了js 闭包。分享给大家供大家参考,具体如下:

1.什么是闭包

定义:是指有权访问另一个函数作用域中的变量的函数

创建闭包:在一个函数内部创建另一个函数

基本特点 在返回的匿名函数中 可以调用外部函数的变量 如下例中所示 内部函数(匿名函数) 可以访问外部函数的变量num 形式如a[num] 原因是匿名函数作用域链中包括外部函数test1的作用域

闭包有权访问包含函数内部的所有变量 如下面的 外部函数定义变量d 在闭包中可以直接访问到d (var dd=d)

function test1(num){
     var d;

    return function(a,b){
      var d1=a[num],d2=b[num];
      var dd=d;
 }

  }

实例参考 此时点击产品1 到 产品4 结果都是5 点击匿名函数的作用域链中包括外部函数init的活动对象 都是引用的同一个变量i 都是5 。解决办法 返回的匿名函数 通过立即执行函数 把参数i传给匿名函数

<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8" />
  <title>闭包演示</title>
  <style type="text/css">
    p {background:gold;}
  </style>
  <script type="text/javascript">
    function init() {
      var pAry = document.getElementsByTagName("p");
      for( var i=0; i<pAry.length; i++ ) {
        pAry[i].onclick = function() {
          alert(i);
        }
      }
    }
   
  </script>
</head>
<body onload="init();">
<p>产品 0</p>
<p>产品 1</p>
<p>产品 2</p>
<p>产品 3</p>
<p>产品 4</p>
</body>
</html>

 弹出结果都是5截图 

js 闭包深入理解与实例分析

解决办法:立即执行匿名函数 参数i是循环i的值 传递给num形参 匿名函数里 在创建闭包 可以访问这个传递过来的值num 

pAry[i].onclick = function(num){//......}(i)
<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8" />
  <title>闭包演示</title>
  <style type="text/css">
    p {background:gold;}
  </style>
  <script type="text/javascript">
     /*修改后*/
     function init() {
     var pAry = document.getElementsByTagName("p");
     for( var i=0; i<pAry.length; i++ ) {
     pAry[i].onclick = function(num) {

     return function(){
     alert(num)
     }
     }(i)
     }
     }

  </script>
</head>
<body onload="init();">
<p>产品 0</p>
<p>产品 1</p>
<p>产品 2</p>
<p>产品 3</p>
<p>产品 4</p>
</body>
</html>

结果点击第一展示

js 闭包深入理解与实例分析

还有这样写也是可以的

function a(){
      var pAry = document.getElementsByTagName("p");
      for( var i=0; i<pAry.length; i++ ) {
        (function(num){
          pAry[num].onclick = function() {
            alert(num);
          }
        })(i)
      }
    }

1.1 闭包的原理

-1) 闭包的作用域链 包括 闭包自身的作用域(一般返回匿名函数的作用域),外部函数的作用域(包含的外部函数),全局作用域

-2)通常,函数的作用域和所有变量都会在函数执行结束后被销毁

-3)函数返回一个闭包,这个函数的作用域会一直保存在内存中直到闭包不存在为止

使用闭包可以模仿块级作用域

-1)创建闭包并立即执行这个函数 不会再内存中留下该函数的引用

-2 )结果 函数内部的所有变量都会被立即销毁

2.什么是作用域链


执行环境:定义了变量或函数有权访问其他数据,决定它们各自的行为。

变量对象:每个执行环境都有一个与之关联的变量对象。

执行环境定义的所有变量和函数都保存在变量对象中。编写代码无法访问这个对象,解析器在处理数据时会在后台使用它。

-1)全局执行环境是最外围的一个执行环境

-2)web浏览器中,全局执行环境默认是window对象,因此所有全局变量和函数都是作为window对象的属性和方法创建的

-3)某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义都随之销毁  全局执行环境直到应用程序退出--例如关闭网页或浏览器时才会被销毁

-4)每个函数都有自己的执行环境

作用域链:当代码在一个执行环境中执行时,会创建变量对象 一个作用域链

作用域链用途:保证对执行环境有权访问的所有变量和函数的有序访问

标识符解析:沿着作用域链一级一级的向上搜索标识符的过程。

函数参数也被当做变量来看待,因此访问规则与执行环境中的其它变量相同。 例子:下面函数chageColor(num){} 在闭包里tempColor(a){}里可用a[num]访问

实例解析

<script type="text/javascript">
  /*全局变量*/
  var color = 'red' ;

  function changeColor(num){
    var otherColor = 'blue',
      another =color,
     chage = changeColor();


      function tempColor(a){
         var temp = otherColor,
           temp2 = color,
           temp3 = changeColor();/*这里可以访问上层执行环境otherColor another chage 和全局color*/
         var u =a[num];


      }

  }
</script>

全局 window

             |

             |-------------color 全局变量

             |------------changeColor()

                                             |

                                             |---------------otherColor(局部变量 还有两个就是调用的上层全局环境里的color变量和函数chageColor)

                                             |---------------tempColor()

                                                                               |-------------------h(变量h不能被上层执行环境调用 只能在tempColor()里调用 标识符向上搜索沿着作用域链 这个环境里可以调用外层环境和全局环境的变量)

参考:

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
phpwind放自动注册方法
Dec 02 Javascript
在js中使用&quot;with&quot;语句中跨frame的变量引用问题
Mar 08 Javascript
不要小看注释掉的JS 引起的安全问题
Dec 27 Javascript
使用jquery动态加载javascript以减少服务器压力
Oct 29 Javascript
JS实现的4种数字千位符格式化方法分享
Mar 02 Javascript
DeviceOne 让你一见钟情的App快速开发平台
Feb 17 Javascript
完美解决jQuery fancybox ie 无法显示关闭按钮的问题
Nov 29 Javascript
wap手机端解决返回上一页的js实例
Dec 08 Javascript
新手必须知的Node.js 4个JavaScript基本概念
Sep 16 Javascript
Vue 进阶之路(三)
Apr 18 Javascript
vue 输入电话号码自动按3-4-4分割功能的实现代码
Apr 30 Javascript
jQuery实现放大镜案例
Oct 19 jQuery
JS一次前端面试经历记录
Mar 19 #Javascript
jQuery实现点击滚动到指定元素上的方法分析
Mar 19 #jQuery
浅析TypeScript 命名空间
Mar 19 #Javascript
JavaScript计算出两个数的差值
Mar 19 #Javascript
JavaScript利用键盘码控制div移动
Mar 19 #Javascript
js实现百度登录窗口拖拽效果
Mar 19 #Javascript
js实现随机抽奖
Mar 19 #Javascript
You might like
分享微信扫码支付开发遇到问题及解决方案-附Ecshop微信支付插件
2015/08/23 PHP
CodeIgniter整合Smarty的方法详解
2017/08/25 PHP
Yii2.0使用阿里云OSS的SDK上传图片、下载、删除图片示例
2017/09/20 PHP
整理的比较全的event对像在ie与firefox浏览器中的区别
2013/11/25 Javascript
JavaScript打印网页指定区域的例子
2014/05/03 Javascript
jQuery学习笔记之 Ajax操作篇(一) - 数据加载
2014/06/23 Javascript
node.js中的fs.utimes方法使用说明
2014/12/15 Javascript
JS打开新窗口防止被浏览器阻止的方法
2015/01/03 Javascript
jQuery中slice()方法用法实例
2015/01/07 Javascript
jQuery实现冻结表头的方法
2015/03/09 Javascript
jQuery实现当前页面标签高亮显示的方法
2015/03/10 Javascript
JavaScript中的this关键字使用方法总结
2015/03/13 Javascript
JavaScript中string对象
2015/06/12 Javascript
教你如何终止JQUERY的$.AJAX请求
2016/02/23 Javascript
js实现控制textarea输入字符串的个数,鼠标按下抬起判断输入字符数
2016/10/25 Javascript
React/Redux应用使用Async/Await的方法
2017/11/16 Javascript
node事件循环和process模块实例分析
2020/02/14 Javascript
简单的连接MySQL与Python的Bottle框架的方法
2015/04/30 Python
Python队列的定义与使用方法示例
2017/06/24 Python
使用Python写一个贪吃蛇游戏实例代码
2017/08/21 Python
Python中将变量按行写入txt文本中的方法
2018/04/03 Python
对python中的乘法dot和对应分量相乘multiply详解
2018/11/14 Python
对python当中不在本路径的py文件的引用详解
2018/12/15 Python
Python面向对象之类的定义与继承用法示例
2019/01/14 Python
pandas.read_csv参数详解(小结)
2019/06/21 Python
python3 常见解密加密算法实例分析【base64、MD5等】
2019/12/19 Python
Python3 ffmpeg视频转换工具使用方法解析
2020/08/10 Python
让你相见恨晚的十个Python骚操作
2020/11/18 Python
python爬虫分布式获取数据的实例方法
2020/11/26 Python
比利时买床:Beter Bed
2017/12/06 全球购物
阿玛尼美妆俄罗斯官网:Giorgio Armani Beauty RU
2020/07/19 全球购物
远程调用的原理
2014/07/05 面试题
酒店保安员岗位职责
2014/01/31 职场文书
小学信息技术教学反思
2014/02/10 职场文书
2015年采购部工作总结
2015/04/23 职场文书
ant design charts 获取后端接口数据展示
2022/05/25 Javascript